library(scPipe)


Registered S3 method overwritten by 'GGally':
  method from   
  +.gg   ggplot2
library(scater)
library(scran)
library(ggplot2)
library(Seurat)

Attaching package: ‘Seurat’

The following object is masked from ‘package:SummarizedExperiment’:

    Assays
library(cowplot)

********************************************************
Note: As of version 1.0.0, cowplot does not change the
  default ggplot2 theme anymore. To recover the previous
  behavior, execute:
  theme_set(theme_cowplot())
********************************************************
library(ggpubr)
Loading required package: magrittr

Attaching package: ‘magrittr’

The following object is masked from ‘package:tidyr’:

    extract


Attaching package: ‘ggpubr’

The following object is masked from ‘package:cowplot’:

    get_legend
library(RColorBrewer)
library(sctransform)
library(flowCore)

Attaching package: ‘flowCore’

The following object is masked from ‘package:scater’:

    normalize

The following object is masked from ‘package:BiocGenerics’:

    normalize
library(pheatmap)
library(dplyr)
library(readr)
library(ggrepel)
gene_filter = function(sce){
  keep1 = (apply(counts(sce), 1, function(x) mean(x[x>0])) > 1.1)  # average count larger than 1.1
  keep2 = (rowSums(counts(sce)>0) > 5) # expressed in more than 5 cells
  sce = sce[(keep1 & keep2), ]
  return(sce)
}
scran_norm = function(sce){
  sce = computeSumFactors(sce)
  sce = normalize(sce)
  return(sce)
}
scran_high_var = function(sce,topn=3000){
  var.fit <- trendVar(sce, method="loess", use.spikes=FALSE)
  var.out <- decomposeVar(sce, var.fit)
  hvg.out <- var.out[order(var.out$bio, decreasing=TRUE)[1:topn], ]
  rowData(sce)$hi_var = FALSE
  rowData(sce)$hi_var[rownames(rowData(sce)) %in% rownames(hvg.out)] = TRUE
  return(sce)
}
sce_RPI4 = create_sce_by_dir(datadir="/Users/tian.l/Dropbox/research/Dach1_paper/NN179/RPI4",organism="mmusculus_gene_ensembl",gene_id_type="ensembl_gene_id")
sce_RPI6 = create_sce_by_dir(datadir="/Users/tian.l/Dropbox/research/Dach1_paper/NN179/RPI6",organism="mmusculus_gene_ensembl",gene_id_type="ensembl_gene_id")
sce_RPI7 = create_sce_by_dir(datadir="/Users/tian.l/Dropbox/research/Dach1_paper/NN179/RPI7",organism="mmusculus_gene_ensembl",gene_id_type="ensembl_gene_id")
sce_RPI8 = create_sce_by_dir(datadir="/Users/tian.l/Dropbox/research/Dach1_paper/NN179/RPI8",organism="mmusculus_gene_ensembl",gene_id_type="ensembl_gene_id")
sce_RPI4 = calculate_QC_metrics(sce_RPI4)
'spikeNames' is deprecated.
See help("Deprecated")'isSpike' is deprecated.
See help("Deprecated")no ERCC spike-in. Skip `non_ERCC_percent`
Cache found
Cache found
sce_RPI6 = calculate_QC_metrics(sce_RPI6)
'spikeNames' is deprecated.
See help("Deprecated")'isSpike' is deprecated.
See help("Deprecated")no ERCC spike-in. Skip `non_ERCC_percent`
Cache found
Cache found
sce_RPI7 = calculate_QC_metrics(sce_RPI7)
'spikeNames' is deprecated.
See help("Deprecated")'isSpike' is deprecated.
See help("Deprecated")no ERCC spike-in. Skip `non_ERCC_percent`
Cache found
Cache found
sce_RPI8 = calculate_QC_metrics(sce_RPI8)
'spikeNames' is deprecated.
See help("Deprecated")'isSpike' is deprecated.
See help("Deprecated")no ERCC spike-in. Skip `non_ERCC_percent`
Cache found
Cache found
sce_RPI4_qc = detect_outlier(sce_RPI4,comp = 2)
the following QC metrics not found in colData from sce: 'non_ERCC_percent'
sce_RPI6_qc = detect_outlier(sce_RPI6,comp = 2)
the following QC metrics not found in colData from sce: 'non_ERCC_percent'
sce_RPI7_qc = detect_outlier(sce_RPI7,comp = 2)
the following QC metrics not found in colData from sce: 'non_ERCC_percent'
sce_RPI8_qc = detect_outlier(sce_RPI8,comp = 2)
the following QC metrics not found in colData from sce: 'non_ERCC_percent'
sce_RPI4_qc = remove_outliers(sce_RPI4_qc)
sce_RPI6_qc = remove_outliers(sce_RPI6_qc)
sce_RPI7_qc = remove_outliers(sce_RPI7_qc)
sce_RPI8_qc = remove_outliers(sce_RPI8_qc)

sce_RPI4_qc = gene_filter(sce_RPI4_qc)
sce_RPI6_qc = gene_filter(sce_RPI6_qc)
sce_RPI7_qc = gene_filter(sce_RPI7_qc)
sce_RPI8_qc = gene_filter(sce_RPI8_qc)

comm_genes = Reduce(intersect,list(rownames(sce_RPI4_qc),
                                   rownames(sce_RPI6_qc),
                                   rownames(sce_RPI7_qc),
                                   rownames(sce_RPI8_qc)))
sce_RPI4_qc = convert_geneid(sce_RPI4_qc)
Cache found
Number of NA in new gene id: 24. Duplicated id: -0.5
sce_RPI6_qc = convert_geneid(sce_RPI6_qc)
Cache found
Number of NA in new gene id: 12. Duplicated id: -0.5
sce_RPI7_qc = convert_geneid(sce_RPI7_qc)
Cache found
Number of NA in new gene id: 12. Duplicated id: -0.5
sce_RPI8_qc = convert_geneid(sce_RPI8_qc)
Cache found
Number of NA in new gene id: 16. Duplicated id: -0.5
comm_genes = Reduce(intersect,list(rownames(sce_RPI4_qc),
                                   rownames(sce_RPI6_qc),
                                   rownames(sce_RPI7_qc),
                                   rownames(sce_RPI8_qc)))

comm_genes = comm_genes[!grepl("ENSMUSG",comm_genes)]
comm_genes = comm_genes[!grepl("ERCC",comm_genes)]
comm_genes = comm_genes[!grepl("Rik",comm_genes)]
comm_genes = comm_genes[!grepl("Hist",comm_genes)]
comm_genes = comm_genes[!grepl("^Rpl",comm_genes)]
comm_genes = comm_genes[!grepl("^Rps",comm_genes)]
comm_genes = comm_genes[!grepl("^H2ac",comm_genes)]
comm_genes = comm_genes[!grepl("^Gm",comm_genes)]
comm_genes = comm_genes[!grepl("^mt-",comm_genes)]

sce_RPI4_qc = sce_RPI4_qc[comm_genes,]
sce_RPI6_qc = sce_RPI6_qc[comm_genes,]
sce_RPI7_qc = sce_RPI7_qc[comm_genes,]
sce_RPI8_qc = sce_RPI8_qc[comm_genes,]

colnames(sce_RPI4_qc) = paste("RPI4",colnames(sce_RPI4_qc),sep="_")
colnames(sce_RPI6_qc) = paste("RPI6",colnames(sce_RPI6_qc),sep="_")
colnames(sce_RPI7_qc) = paste("RPI7",colnames(sce_RPI7_qc),sep="_")
colnames(sce_RPI8_qc) = paste("RPI8",colnames(sce_RPI8_qc),sep="_")
sce_RPI4_qc$batch = "RPI4"
sce_RPI6_qc$batch = "RPI6"
sce_RPI7_qc$batch = "RPI7"
sce_RPI8_qc$batch = "RPI8"
sce_RPI4_qc = logNormCounts(sce_RPI4_qc)
sce_RPI6_qc = logNormCounts(sce_RPI6_qc)
sce_RPI7_qc = logNormCounts(sce_RPI7_qc)
sce_RPI8_qc = logNormCounts(sce_RPI8_qc)
library(SingleR)
ref.se <- ImmGenData()
snapshotDate(): 2019-10-22
see ?SingleR and browseVignettes('SingleR') for documentation
loading from cache
see ?SingleR and browseVignettes('SingleR') for documentation
loading from cache
pred.RPI4 <- SingleR(test=sce_RPI4_qc, ref=ref.se, labels=ref.se$label.fine)
pred.RPI6 <- SingleR(test=sce_RPI6_qc, ref=ref.se, labels=ref.se$label.fine)
pred.RPI7 <- SingleR(test=sce_RPI7_qc, ref=ref.se, labels=ref.se$label.fine)
pred.RPI8 <- SingleR(test=sce_RPI8_qc, ref=ref.se, labels=ref.se$label.fine)
tmp_t = table(c(pred.RPI4$pruned.labels, pred.RPI6$pruned.labels, pred.RPI7$pruned.labels, pred.RPI8$pruned.labels))
tmp_t[tmp_t>10]

         B cells (proB.CLP)         B cells (proB.FrBC)         B cells (proB.FRBC)            Stem cells (MLP) Stem cells (SC.CD150-CD48-) 
                         17                          12                          11                         222                          19 
      Stem cells (SC.LT34F)      Stem cells (SC.MPP34F)       Stem cells (SC.ST34F)        Stem cells (SC.STSL)             T cells (T.ETP) 
                        178                         440                         113                         208                          26 
#kept_celltype = c("B cells (proB.CLP)","T cells (T.ETP)","Stem cells (MLP)","Stem cells (SC.STSL)","Stem cells (SC.MPP34F)","Stem cells (SC.LT34F)","Stem cells (SC.CMP.DR)","Stem cells (GMP)","Stem cells (SC.CDP)")
kept_celltype = colnames(pred.RPI4$scores)
comb_scores = rbind(pred.RPI4$scores[,kept_celltype],
                    pred.RPI6$scores[,kept_celltype],
                    pred.RPI7$scores[,kept_celltype],
                    pred.RPI8$scores[,kept_celltype])
rownames(comb_scores) = c(rownames(pred.RPI4), rownames(pred.RPI6), rownames(pred.RPI7), rownames(pred.RPI8))
C084_Naik_SaraTomei_NN179_SeqPrimer_layout_Jan20_ST_ <-readxl::read_excel("~/Dropbox/research/Dach1_paper/NN179/C084_Naik_SaraTomei_NN179_SeqPrimer layout_Jan20(ST).xlsx", sheet = "Sample & Index", skip = 3)
New names:
* `(separate index read)` -> `(separate index read)...7`
* `(separate index read)` -> `(separate index read)...8`
FACS_anno = C084_Naik_SaraTomei_NN179_SeqPrimer_layout_Jan20_ST_[,c("Well position","(separate index read)...7","<R660/20-A>: cKit APC","<V450/50-A>: PIR-A PB","<V660/20-A>: IL7R BV650","<R780/60-A>: CD48 APC Cy7","<B695/40-A>: CD11b BB700","<Y780/60-A>: CD150 PE Cy7","<Y670/14-A>: PI","<Y610/20-A>: Sca1 A594","<B530/30-A>: Dach1 GFP","<V610/20-A>: CD16/32 BV605","<Y582/15-A>: Flt3 PE")]
FACS_anno = FACS_anno[!is.na(FACS_anno$`<V450/50-A>: PIR-A PB`),]
FACS_anno$`(separate index read)...7` = gsub(" ", "", FACS_anno$`(separate index read)...7`, fixed = TRUE)
FACS_anno$cell_id = paste(FACS_anno$`(separate index read)...7`,FACS_anno$`Well position`,sep="_")
FACS_anno = FACS_anno[!is.na(FACS_anno$`<B530/30-A>: Dach1 GFP`),]

srt4 <- CreateSeuratObject(counts = counts(sce_RPI4_qc),meta.data=as.data.frame(colData(sce_RPI4_qc)))
srt4 <- SCTransform(object = srt4, variable.features.n=2000, verbose = FALSE)
srt6 <- CreateSeuratObject(counts = counts(sce_RPI6_qc),meta.data=as.data.frame(colData(sce_RPI6_qc)))
srt6 <- SCTransform(object = srt6, variable.features.n=2000,verbose = FALSE)
srt7 <- CreateSeuratObject(counts = counts(sce_RPI7_qc),meta.data=as.data.frame(colData(sce_RPI7_qc)))
srt7 <- SCTransform(object = srt7, variable.features.n=2000,verbose = FALSE)
srt8 <- CreateSeuratObject(counts = counts(sce_RPI8_qc),meta.data=as.data.frame(colData(sce_RPI8_qc)))
srt8 <- SCTransform(object = srt8, variable.features.n=2000,verbose = FALSE)
options(future.globals.maxSize = 2100 * 1024^2)
immune.features <- SelectIntegrationFeatures(object.list = list(srt4, srt6, srt7, srt8), nfeatures = 2000, verbose = FALSE)
immune.combined <- PrepSCTIntegration(object.list = list(srt4, srt6, srt7, srt8), anchor.features = immune.features, verbose = FALSE)
immune.anchors <- FindIntegrationAnchors(object.list = immune.combined, normalization.method = "SCT", 
                                         anchor.features = immune.features, verbose = FALSE)
srt_combine <- IntegrateData(anchorset = immune.anchors, normalization.method = "SCT", dims = 1:20,
                                 verbose = FALSE)
srt_combine <- RunPCA(object = srt_combine, verbose = FALSE)
srt_combine <- RunUMAP(object = srt_combine, dims = 1:20, verbose = FALSE)
srt_combine <- FindNeighbors(object = srt_combine, dims = 1:20, verbose = FALSE)
srt_combine <- FindClusters(object = srt_combine, verbose = FALSE)
# Visualization
p1 <- DimPlot(srt_combine, reduction = "umap", group.by = "batch")
p2 <- DimPlot(srt_combine, reduction = "umap", label = TRUE)
plot_grid(p1, p2)

FACS_anno = as.data.frame(FACS_anno)
FACS_anno = FACS_anno[match(rownames(srt_combine@meta.data),FACS_anno$cell_id),]
srt_combine@meta.data = cbind(srt_combine@meta.data, FACS_anno)
srt_combine = srt_combine[,!is.na(srt_combine$`<B530/30-A>: Dach1 GFP`)]
FeaturePlot(srt_combine,features = colnames(srt_combine@meta.data)[23:33],pt.size=0.1,max.cutoff="q95",ncol=3)

FeaturePlot(srt_combine,features =c("Rag1","Rag2","Dntt"),pt.size=0.1,max.cutoff="q95")
The following requested variables were not found: Rag2

srt_combine.markers <- FindAllMarkers(srt_combine, only.pos = TRUE,verbose=FALSE)
top10 <- srt_combine.markers %>% group_by(cluster) %>% top_n(n = 10, wt = avg_logFC)
DoHeatmap(srt_combine, features = top10$gene)

s.genes <- tolower(cc.genes$s.genes)
g2m.genes <- tolower(cc.genes$g2m.genes)
simpleCap <- function(x) {
  paste(toupper(substring(x, 1,1)), substring(x, 2),
      sep="")
}
s.genes = simpleCap(s.genes)
g2m.genes = simpleCap(g2m.genes)
srt_combine <- CellCycleScoring(srt_combine, s.features = s.genes, g2m.features = g2m.genes, set.ident = FALSE)
The following features are not present in the object: Mcm4, Gins2, Dtl, Prim1, Mlf1ip, Rfc2, Rpa2, Nasp, Rad51ap1, Gmnn, Wdr76, Ccne2, Ubr7, Pold3, Rad51, Cdc45, Exo1, Tipin, Dscc1, Blm, Casp8ap2, Clspn, Chaf1b, Brip1, E2f8, not searching for symbol synonymsThe following features are not present in the object: Tpx2, Ndc80, Nuf2, Tacc3, Fam64a, Ckap2, Bub1, Gtse1, Kif20b, Cdca3, Hn1, Ttk, Cdc25c, Kif2c, Rangap1, Dlgap5, Cdca2, Aurka, Psrc1, Anln, Lbr, Ckap5, Ctcf, Nek2, not searching for symbol synonyms
srt_combine$CC.Difference <- srt_combine$S.Score - srt_combine$G2M.Score
head(srt_combine[[]])
DimPlot(srt_combine, reduction = "umap", group.by = "Phase")

#srt_filter_cc <- ScaleData(srt_combine, vars.to.regress = c("CC.Difference"), features = rownames(srt_combine),verbose = FALSE)
srt_filter_cc <- ScaleData(srt_combine,  vars.to.regress = c("S.Score", "G2M.Score"), features = rownames(srt_combine),verbose = FALSE)
srt_filter_cc <- RunPCA(object = srt_filter_cc, verbose = FALSE)
srt_filter_cc <- RunUMAP(object = srt_filter_cc, dims = 1:20, verbose = FALSE)
srt_filter_cc <- FindNeighbors(object = srt_filter_cc, dims = 1:20, verbose = FALSE)
srt_filter_cc <- FindClusters(object = srt_filter_cc, resolution = 1., verbose = FALSE)
# Visualization
p1 <- DimPlot(srt_filter_cc, reduction = "umap", group.by = "Phase")
p2 <- DimPlot(srt_filter_cc, reduction = "umap", label = TRUE)
plot_grid(p1, p2)

srt_filter_cc.markers <- FindAllMarkers(srt_filter_cc, only.pos = TRUE,verbose=FALSE)
top10 <- srt_filter_cc.markers %>% group_by(cluster) %>% top_n(n = 10, wt = avg_logFC)
DoHeatmap(srt_filter_cc, features = top10$gene)

FeaturePlot(srt_filter_cc,features = colnames(srt_filter_cc@meta.data)[23:33],pt.size=0.5,max.cutoff="q95",ncol=3)

ggplot(data=NULL,aes(x=log2(srt_filter_cc$`<Y582/15-A>: Flt3 PE`),y=log2(srt_filter_cc$`<B530/30-A>: Dach1 GFP`),col=as.factor(srt_filter_cc$seurat_clusters)))+
  geom_point()+
  scale_color_brewer(palette = "Set1")+
  theme_bw()

mk_genes = unique(srt_filter_cc.markers[srt_filter_cc.markers$p_val_adj<0.05,]$gene)

DE_expr = srt_filter_cc@assays$SCT@scale.data[mk_genes,]

database = "immgen"
immgen_samples <- read.delim(paste0("/Users/tian.l/Dropbox/research/Dach1_paper/ref_data/",database,"_samples.txt"), stringsAsFactors=FALSE)
immgen_probes <- read.delim(paste0("/Users/tian.l/Dropbox/research/Dach1_paper/ref_data/",database,"_probes.txt"), header=FALSE, stringsAsFactors=FALSE)
immgen_expression <- read.delim(paste0("/Users/tian.l/Dropbox/research/Dach1_paper/ref_data/",database,"_expression.txt"), stringsAsFactors=FALSE)

library('biomaRt')
mart <- useDataset("mmusculus_gene_ensembl", useMart("ensembl"))
G_list <- getBM(filters= "ensembl_gene_id", attributes= c("ensembl_gene_id", "external_gene_name", "description"),values=immgen_probes$V2 ,mart=mart)
Cache found
immgen_probes = immgen_probes[immgen_probes$V2 %in% G_list$ensembl_gene_id,]
G_list = G_list[match(immgen_probes$V2, G_list$ensembl_gene_id),]
immgen_probes$external_gene_name = G_list$external_gene_name

immgen_expression = immgen_expression[immgen_expression$probeId %in% immgen_probes$V1,]
immgen_probes = immgen_probes[immgen_probes$V1 %in% immgen_expression$probeId,]
immgen_probes = immgen_probes[match(immgen_expression$probeId, immgen_probes$V1),]
immgen_expression$gene_id = immgen_probes$external_gene_name
immgen_expression = immgen_expression[!duplicated(immgen_expression$gene_id),]
g_i = immgen_expression$gene_id
immgen_expression = immgen_expression[,!(colnames(immgen_expression) %in% c("probeId","gene_id"))]
immgen_expression = as.matrix(immgen_expression)
rownames(immgen_expression) = g_i

table(immgen_samples$cell_lineage)

        ab T cells            B cells    Dendritic cells         gd T cells Innate Lymphocytes        Macrophages          Monocytes        Neutrophils 
                67                 26                 36                 22                 22                 15                  8                  6 
        Stem Cells      Stromal cells 
                14                  8 
immgen_samples$sampleId = gsub("-",".",immgen_samples$sampleId)
#SC_list = immgen_samples[immgen_samples$cell_lineage == "Stem Cells", "sampleId"]

SC_list = c("SC_CDP_BM","SC_CMP_BM","SC_GMP_BM",
            "SC_LTSL_BM","SC_LTSL_BM","SC_MDP_BM",
            "SC_MEP_BM","SC_MPP34F_BM","SC_ST34F_BM",
            "SC_STSL_BM","preB_FrD_BM","B1b_PC")
#SC_list = immgen_samples$sampleId
sub_immgen_expression = immgen_expression[rownames(immgen_expression) %in% rownames(DE_expr), colnames(immgen_expression) %in% SC_list]
sub_immgen_expression = sub_immgen_expression[!duplicated(rownames(sub_immgen_expression)),]
sub_DE_expr = DE_expr[rownames(DE_expr) %in% rownames(sub_immgen_expression),]
sub_DE_expr = sub_DE_expr[!duplicated(rownames(sub_DE_expr)),]
sub_DE_expr = sub_DE_expr[order(rownames(sub_DE_expr)),]
sub_immgen_expression = sub_immgen_expression[order(rownames(sub_immgen_expression)),]


p.val_mat = c()
for (i in 1:ncol(sub_immgen_expression))
{
  p.val_vec = apply(sub_DE_expr, 2, function(x){
  cor.test(x,sub_immgen_expression[,i],
         method = "spearman",
         alternative = "greater",exact=FALSE)$p.value})
  p.val_mat = rbind(p.val_mat,-log10(p.val_vec))
}
rownames(p.val_mat) = colnames(sub_immgen_expression)

# hm_immgen = heatmap.2(p.val_mat[,order(mycl)],trace="none",
#           dendrogram="none",
#           Colv=FALSE,
#           col=hmcol,
#           scale="column",
#           labRow = "",
#           #ColSideColors = myClusterSideBar[order(mycl)],
#           labCol = "",
#           density.info="none",
#           key=FALSE)

#p_ma = p.val_mat[,order(mycl)]
#p_ma = p_ma[hm_immgen$rowInd,]

p.val_mat_s = scale(p.val_mat)
p.val_mat_s[p.val_mat_s>2] = 2
p.val_mat_s[p.val_mat_s<(-2)] = -2

pheatmap(p.val_mat_s[,order(srt_filter_cc$seurat_clusters)],cluster_cols = F,show_colnames = F,scale="none",annotation_col = srt_filter_cc@meta.data[,c("seurat_clusters","orig.ident")],filename="figs/immgen_sim_all.pdf",width = 10,height = 20)
comb_scores = comb_scores[colnames(srt_filter_cc),]
comb_scores = scale(comb_scores)
comb_scores[comb_scores>2.5] = 2.5
comb_scores[comb_scores<(-2.5)] = -2.5

pheatmap(comb_scores[order(srt_filter_cc$seurat_clusters),],scale = "none",cluster_rows = FALSE,show_rownames = FALSE,annotation_row = srt_filter_cc@meta.data[,c("seurat_clusters","<V660/20-A>: IL7R BV650")],fontsize = 6,filename="figs/heatmap_singleR_score.pdf",width = 20,height = 10)
top10 <- srt_filter_cc.markers %>% group_by(cluster) %>% top_n(n = 10, wt = -p_val_adj)

top_ge = c()
for(i in 0:(length(unique(srt_filter_cc$seurat_clusters))-1)){
  tmp_mk_df = top10[top10$cluster==i,]
  tmp_mk_df = tmp_mk_df[order(tmp_mk_df$avg_logFC,decreasing = TRUE),]
  if (i %in% c(1, 6)){
    tmp_mk_df = tmp_mk_df[1:6,]
  }else{
    tmp_mk_df = tmp_mk_df[1:3,]
  }
  top_ge = c(top_ge, tmp_mk_df$gene)
}
top_ge = top_ge[top_ge %in% rownames(srt_filter_cc@assays$integrated@scale.data)]
tmp_mat = srt_filter_cc@assays$integrated@scale.data[top_ge,]
#tmp_mat = srt_filter_cc@assays$SCT@scale.data[top_ge,]
tmp_mat[tmp_mat>2.5] = 2.5
tmp_mat[tmp_mat<(-2.5)] = -2.5

anno_df = data.frame(clusters=srt_filter_cc$seurat_clusters,
                     Dach1GFP=srt_filter_cc@meta.data[,"<B530/30-A>: Dach1 GFP"],
                     CD150=srt_filter_cc@meta.data[,"<Y780/60-A>: CD150 PE Cy7"],
                     CD135=srt_filter_cc@meta.data[,"<Y582/15-A>: Flt3 PE"],
                     cKit=srt_filter_cc@meta.data[,"<R660/20-A>: cKit APC"],
                     Sca1=srt_filter_cc@meta.data[,"<Y610/20-A>: Sca1 A594"],
                     CD127=srt_filter_cc@meta.data[,"<V660/20-A>: IL7R BV650"],
                     CD48=srt_filter_cc@meta.data[,"<R780/60-A>: CD48 APC Cy7"],
                     B_cell=comb_scores[,"B cells (B1b)"],
                     CLP=comb_scores[,"B cells (preB.FrD)"],
                     GMP=comb_scores[,"Stem cells (GMP)"],
                     CMP=comb_scores[,"Stem cells (SC.CMP.DR)"],
                     LMPP=comb_scores[,"Stem cells (SC.MPP34F)"],
                     #STSL=comb_scores[,"Stem cells (SC.STSL)"],
                     LTSL=comb_scores[,"Stem cells (SC.LT34F)"],stringsAsFactors = FALSE)

getPalette = colorRampPalette(brewer.pal(9, "Set1"))
col9 = getPalette(9)

ttt = col9[2]
col9[2] = col9[1]
col9[1] = ttt

names(col9) = as.character(0:8)
annotation_colors = list(
  clusters=col9,
  Dach1GFP=BlueAndRed(),
  CD150=BlueAndRed(),
  CD135=BlueAndRed(),
  cKit=BlueAndRed(), 
  CD127=BlueAndRed(),
  Sca1=BlueAndRed()[floor(50*(min(srt_filter_cc$`<Y610/20-A>: Sca1 A594`)-0)/(max(srt_filter_cc$`<Y610/20-A>: Sca1 A594`)-0)):50],  
  CD48=BlueAndRed(),
  GMP=BlueAndRed(),
  B_cell=BlueAndRed(),
  CLP=BlueAndRed(),
  CMP=BlueAndRed(),
  LMPP=BlueAndRed(),
  STSL=BlueAndRed(),
  LTSL=BlueAndRed()
)

#htmp = hclust(dist(anno_df[,c("B_cell","CLP","CMP","LMPP","STSL","LTSL")]))

pheatmap(tmp_mat[,order(srt_filter_cc$seurat_clusters)],
         cluster_cols = FALSE, 
         cluster_rows = FALSE,
         annotation_col = anno_df,
         annotation_colors=annotation_colors,
         show_colnames = FALSE,
         color=PurpleAndYellow(),
         filename="figs/heatmap_with_Seurat_cluster_all_markers.pdf",width = 7,height = 8.5)
library(slingshot)




sds <- slingshot(srt_filter_cc@reductions$umap@cell.embeddings, srt_filter_cc$seurat_clusters, start.clus=3)
Using full covariance matrix

sds@lineages$Lineage3
[1] "3" "0" "1" "6"
order_df = srt_filter_cc@meta.data
order_df = order_df[sds@curves$curve3$ord,]
order_df = order_df[order_df$seurat_clusters %in% sds@lineages$Lineage3,]
order_df_raw = order_df



plot(order_df_raw$`<V660/20-A>: IL7R BV650`, order_df$`<V660/20-A>: IL7R BV650`)

hist(order_df$`<V660/20-A>: IL7R BV650`)

ggarrange(plotlist = plist,ncol=1,align = "h",common.legend = TRUE)

ggsave("figs/pseudotime_FACS_marker.pdf",width=5,height=10)

tmp_expr = srt_filter_cc@assays$integrated@scale.data["Dntt",sds@curves$curve3$ord[srt_filter_cc$seurat_clusters %in% sds@lineages$Lineage3]]
tmp_expr[tmp_expr<quantile(tmp_expr,0.05)] = quantile(tmp_expr,0.05)
tmp_df = data.frame(tmp_expr=tmp_expr,seurat_clusters=order_df$seurat_clusters,stringsAsFactors = FALSE)
tmp_df$move_med =  zoo::rollapplyr(tmp_df$tmp_expr,FUN =median,width = 20)
Error in `$<-.data.frame`(`*tmp*`, move_med, value = c(-0.69749948718038,  : 
  replacement has 918 rows, data has 937
DimPlot(srt_filter_cc, reduction = "umap", label = FALSE,cols = col9)+theme(legend.position = "none",line = element_blank(),
                                                                            axis.text  =element_blank(),
        title = element_blank())
ggsave("figs/umap_col_by_cluster.pdf",width = 4.5,height = 4.5)

https://www.ncbi.nlm.nih.gov/pmc/articles/PMC4542150/

#LT-HSC: CD135-  CD150+  CD48-
is_LTHSC = (srt_filter_cc$`<Y582/15-A>: Flt3 PE`<3.5) & (srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`>3.5) & (srt_filter_cc$`<R780/60-A>: CD48 APC Cy7`<3.3)
#ST-HSC: CD135-  CD150-  CD48-
is_STHSC = (srt_filter_cc$`<Y582/15-A>: Flt3 PE`<3.5) & (srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`<3.5) & (srt_filter_cc$`<R780/60-A>: CD48 APC Cy7`<3.3)
#MPP2: CD135-  CD150+  CD48+
is_MPP2 = (srt_filter_cc$`<Y582/15-A>: Flt3 PE`<3.5) & (srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`>3.5) & (srt_filter_cc$`<R780/60-A>: CD48 APC Cy7`>3.3)
#MPP3: CD135-  CD150-  CD48+
is_MPP3 = (srt_filter_cc$`<Y582/15-A>: Flt3 PE`<3.5) & (srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`<3.5) & (srt_filter_cc$`<R780/60-A>: CD48 APC Cy7`>3.3)
is_MPP4 = (srt_filter_cc$`<Y582/15-A>: Flt3 PE`>3.5) & (srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`<3.5) 
is_CLP = srt_filter_cc$`<V660/20-A>: IL7R BV650`>3
srt_filter_cc$gate = "MPP2"
srt_filter_cc$gate[is_LTHSC]="LT-HSC"
srt_filter_cc$gate[is_STHSC]="ST-HSC"
srt_filter_cc$gate[is_MPP2]="MPP2"
srt_filter_cc$gate[is_MPP3]="MPP3"
srt_filter_cc$gate[is_MPP4]="MPP4"
srt_filter_cc$gate[is_CLP]="CLP"

DimPlot(srt_filter_cc, group.by = "gate", label = FALSE)+theme(line = element_blank(),
                                                                            axis.text  =element_blank(),
        title = element_blank())

srt_filter_cc$FACS_CT = "LMPP"
srt_filter_cc$FACS_CT[srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`>3.5 & srt_filter_cc$`<Y582/15-A>: Flt3 PE`<3.5] = "LT + MPP2"
srt_filter_cc$FACS_CT[srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`<3.5 & srt_filter_cc$`<Y582/15-A>: Flt3 PE`<3.5] = "ST + MPP3"
srt_filter_cc$FACS_CT[srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`<3.5 & srt_filter_cc$`<Y582/15-A>: Flt3 PE`>3.5] = "LMPP"
srt_filter_cc$FACS_CT[srt_filter_cc$`<V660/20-A>: IL7R BV650`>3] = "CLP"
DimPlot(srt_filter_cc, group.by = "FACS_CT", label = FALSE)+theme(line = element_blank(),
                                                                            axis.text  =element_blank(),
        title = element_blank())
ggsave("figs/umap_col_by_FACS_gate.pdf",width = 5.5,height = 4.5)

p1 = FeaturePlot(srt_filter_cc,features = c("Dntt"),pt.size=0.5,max.cutoff="q95",ncol=4,cols=BlueAndRed())+theme(line = element_blank(),text=element_text(size=12),
                                                                            axis.text  =element_blank(),axis.title = element_blank(),legend.position="none")
p2 = FeaturePlot(srt_filter_cc,features = c("Satb1"),pt.size=0.5,max.cutoff="q95",ncol=4,cols=BlueAndRed())+theme(line = element_blank(),text=element_text(size=12),
                                                                            axis.text  =element_blank(),axis.title = element_blank(),legend.position="none")
p3 = FeaturePlot(srt_filter_cc,features = c("Notch1"),pt.size=0.5,max.cutoff="q95",ncol=4,cols=BlueAndRed())+theme(line = element_blank(),
                                                                            axis.text  =element_blank(),axis.title = element_blank(),text=element_text(size=12),legend.position="none")
p4 = FeaturePlot(srt_filter_cc,features = c("Vpreb1"),pt.size=0.5,max.cutoff="q95",ncol=4,cols=BlueAndRed())+theme(line = element_blank(),
                                                                            axis.text  =element_blank(),axis.title = element_blank(),text=element_text(size=12),legend.position="none")

ggarrange(p1,p2,p3,p4,ncol=2,nrow=2)
ggsave("figs/umap_marker_genes.pdf",width = 5,height = 5)

p1 = FeaturePlot(srt_filter_cc,features = c("<Y780/60-A>: CD150 PE Cy7"),pt.size=0.5,max.cutoff="q95",ncol=4,cols=BlueAndRed())+labs(title="CD150")+theme(line = element_blank(),text=element_text(size=12),
                                                                            axis.text  =element_blank(),axis.title = element_blank(),legend.position="none")

p2 = FeaturePlot(srt_filter_cc,features = c("<Y582/15-A>: Flt3 PE"),pt.size=0.5,max.cutoff="q95",ncol=4,cols=BlueAndRed())+labs(title="CD135 (Flt3)")+theme(line = element_blank(),text=element_text(size=12),
                                                                            axis.text  =element_blank(),axis.title = element_blank(),legend.position="none")

p3 = FeaturePlot(srt_filter_cc,features = c("<B530/30-A>: Dach1 GFP"),pt.size=0.5,max.cutoff="q95",ncol=4,cols=BlueAndRed())+labs(title=" Dach1-GFP")+theme(line = element_blank(),text=element_text(size=12),
                                                                            axis.text  =element_blank(),axis.title = element_blank(),legend.position="none")
p4 = FeaturePlot(srt_filter_cc,features = c("<V660/20-A>: IL7R BV650"),pt.size=0.5,max.cutoff="q95",ncol=4,cols=BlueAndRed())+labs(title="IL7R")+theme(line = element_blank(),text=element_text(size=12),
                                                                            axis.text  =element_blank(),axis.title = element_blank(),legend.position="none")

ggarrange(p1,p2,p3,p4,ncol=4,nrow=1)
ggsave("figs/umap_marker_FACS.pdf",width = 10,height = 3)


pdf("figs/umap_all_lineage.pdf")
plot(srt_filter_cc@reductions$umap@cell.embeddings, col = col9[srt_filter_cc$seurat_clusters], pch=16, cex=0.7,asp = 1,axes = FALSE,xlab='',ylab='')
lines(sds, lwd=2, col='black')
legend('topleft',legend=names(col9),col=col9,pch=16,title="clusters")
dev.off()
null device 
          1 
clp_lpp_de = FindMarkers(srt_filter_cc,ident.1=c("1","6"),verbose = FALSE)
srt_filter_cc$LMPP_gate = "others"
srt_filter_cc$LMPP_gate[srt_filter_cc$FACS_CT=="LMPP"] = "LMPP"

p1 = DimPlot(srt_filter_cc, group.by = "LMPP_gate", order=c("LMPP","others"), cols = c("grey","black"), label = FALSE)+theme(legend.position = "none",line = element_blank(),
                                                                            axis.text  =element_blank(),
        title = element_blank())

srt_filter_cc$flt_gate = "others"
srt_filter_cc$flt_gate[srt_filter_cc$`<Y582/15-A>: Flt3 PE`>3.57 & srt_filter_cc$`<B530/30-A>: Dach1 GFP`>2.8 & srt_filter_cc$`<V660/20-A>: IL7R BV650`<3] = "Dach1+LMPP"

p2 = DimPlot(srt_filter_cc, group.by = "flt_gate", order=c("Dach1+LMPP","others"), cols = c("grey","black"), label = FALSE)+theme(legend.position = "none",line = element_blank(),
                                                                            axis.text  =element_blank(),
        title = element_blank())

srt_filter_cc$LPP_gate = "others"
srt_filter_cc$LPP_gate[srt_filter_cc$`<Y582/15-A>: Flt3 PE`>3.57 & srt_filter_cc$`<B530/30-A>: Dach1 GFP`<2.5 & srt_filter_cc$`<V660/20-A>: IL7R BV650`<3] = "LPP"

p3 = DimPlot(srt_filter_cc, group.by = "LPP_gate", order=c("LPP","others"), cols = c("grey","black"), label = FALSE)+theme(legend.position = "none",line = element_blank(),
                                                                            axis.text  =element_blank(),
        title = element_blank())

srt_filter_cc$CLP_gate = "others"
srt_filter_cc$CLP_gate[srt_filter_cc$FACS_CT=="CLP"] = "CLP"

p4 = DimPlot(srt_filter_cc, group.by = "CLP_gate", order=c("CLP","others"), cols = c("grey","black"), label = FALSE)+theme(legend.position = "none",line = element_blank(),
                                                                            axis.text  =element_blank(),
        title = element_blank())

ggarrange(p1,p2,p3,p4,ncol=4,nrow=1)
ggsave("figs/umap_LPP_gate.pdf",width = 12,height = 3)

combined_gate = rep(".",ncol(srt_filter_cc))
combined_gate[srt_filter_cc$LMPP_gate=="LMPP"] = "other LMPPs"
combined_gate[srt_filter_cc$flt_gate =="Dach1+LMPP"] = "Dach1+LMPP"
combined_gate[srt_filter_cc$LPP_gate =="LPP"] = "LPP"
combined_gate[srt_filter_cc$CLP_gate =="CLP"] = "CLP"
facs_new = srt_filter_cc$FACS_CT
facs_new[combined_gate=="Dach1+LMPP"] = "Dach1+LMPP"
facs_new[combined_gate=="LPP"] = "LPP"

ggplot(data=NULL,aes(x=srt_filter_cc$`<Y582/15-A>: Flt3 PE`[!srt_filter_cc$FACS_CT=="CLP"],y=srt_filter_cc$`<B530/30-A>: Dach1 GFP`[!srt_filter_cc$FACS_CT=="CLP"],col=facs_new[!srt_filter_cc$FACS_CT=="CLP"]))+
  geom_point(size=1)+
  theme_bw()+
  scale_color_manual(values = c("LMPP"="#E7B800", "LT + MPP2"="#00AFBB","ST + MPP3"="#CC79A7","Dach1+LMPP"="#0CA552","LPP"="#EA2424","CLP"="#9F4A18")) +
  #scale_color_manual(values = pal)+
  labs(x="CD135 (Flt3)",y="Dach1-GFP",col="")+
  theme(legend.position="top",panel.grid.major = element_blank(), panel.grid.minor = element_blank(),
panel.background = element_blank(), axis.line = element_line(colour = "black"))
ggsave("figs/CD135_Dach1_col_by_FACS.pdf",width = 4.,height = 4.)

pal =  c("LMPP"="#E7B800", "LT + MPP2"="#00AFBB","ST + MPP3"="#CC79A7","Dach1+LMPP"="#0CA552","LPP"="#EA2424","CLP"="#9F4A18","."="grey80")
combined_gate_n = facs_new
combined_gate_n[!(srt_filter_cc$seurat_clusters %in% sds@lineages$Lineage3)] = "."
pdf("figs/umap_LPP_lineage.pdf")
plot(srt_filter_cc@reductions$umap@cell.embeddings, col = pal[combined_gate_n], pch=16, cex=0.9,asp = 1,axes = FALSE,xlab='',ylab='')
lines(sds@curves$curve3, lwd=2, col='black')
legend('topright',legend=names(pal) ,col=pal,pch=16,title="FACS gating",pt.cex=1.5,cex=1.2)
dev.off()
null device 
          1 
#pdf("figs/umap_all_lineage.pdf")
#plot(srt_filter_cc@reductions$umap@cell.embeddings, col = pal[srt_filter_cc$FACS_CT], pch=16, cex=0.7,asp = 1,axes = FALSE,xlab='',ylab='')
#lines(sds, lwd=2, col='black')
#legend('topleft',legend=levels(as.factor(srt_filter_cc$FACS_CT)),col=pal,pch=16,title="FACS gating")
#dev.off()
top_ge = c("Mpl","Hlf","Satb1","Il12a","Vpreb1","Blnk","Cd79a","Rag1","Pax5","Ly6d","Dntt","Irf8","Notch1","Plac8")

tmp_mat = srt_filter_cc@assays$integrated@scale.data[unique(top_ge),rownames(order_df)]
#tmp_mat = tmp_mat[,colnames(tmp_mat) %in% rownames(srt_filter_cc@meta.data)[srt_filter_cc$FACS_CT %in% c("CLP","LMPP")]]
tmp_mat[tmp_mat>2.5] = 2.5
tmp_mat[tmp_mat<(-2.5)] = -2.5

anno_df = data.frame(clusters=srt_filter_cc$seurat_clusters,
                     FACS_gating=facs_new,
                     Dach1GFP=srt_filter_cc$`<B530/30-A>: Dach1 GFP`,
                     CD135=srt_filter_cc$`<Y582/15-A>: Flt3 PE`,
                     CD127=srt_filter_cc$`<V660/20-A>: IL7R BV650`,
                     #CD150=srt_filter_cc$`<Y780/60-A>: CD150 PE Cy7`,
                     stringsAsFactors = FALSE)

annotation_colors = list(
  clusters=col9,
  Dach1GFP=BlueAndRed(),
  CD150=BlueAndRed(),
  CD135=BlueAndRed(),
  CD127=BlueAndRed(),
  proB_CLP_BM=BlueAndRed(),
  SC_CMP_BM=BlueAndRed(),
  SC_MEP_BM=BlueAndRed(),
  SC_STSL_BM=BlueAndRed(),
  SC_LTSL_BM=BlueAndRed(),
  FACS_gating=pal
)

pheatmap(tmp_mat,
         cluster_cols = FALSE, 
         cluster_rows = TRUE,
         annotation_col = anno_df,
         annotation_colors=annotation_colors,
         show_colnames = FALSE,
         color=PurpleAndYellow(),
         filename="figs/heatmap_slingshot_S.pdf",width = 5,height = 3.5)

pheatmap(tmp_mat,
         cluster_cols = FALSE, 
         cluster_rows = TRUE,
         annotation_col = anno_df,
         annotation_colors=annotation_colors,
         show_colnames = FALSE,
         color=PurpleAndYellow(),
         filename="figs/heatmap_slingshot_L.pdf",width = 6.5,height = 10)
srt_filter_cc$clp_lpp_gate = srt_filter_cc$CLP_gate 
srt_filter_cc$clp_lpp_gate[srt_filter_cc$LPP_gate=="LPP"] = "LPP"

srt_filter_cc_lpp = srt_filter_cc[,!(srt_filter_cc$clp_lpp_gate == "others")]
p1 = VlnPlot(srt_filter_cc_lpp,features=c("Il12a"),pt.size=0.3,group.by="clp_lpp_gate")+scale_fill_manual(values = c("#FA9A95","#C30000"))+theme(legend.position = "none",axis.title = element_blank(),axis.text.x = element_blank())
p2 = VlnPlot(srt_filter_cc_lpp,features=c("Satb1"),pt.size=0.3,group.by="clp_lpp_gate")+scale_fill_manual(values = c("#FA9A95","#C30000"))+theme(legend.position = "none",axis.title = element_blank(),axis.text.x = element_blank())
p3 = VlnPlot(srt_filter_cc_lpp,features=c("Macroh2a1"),pt.size=0.3,group.by="clp_lpp_gate")+scale_fill_manual(values = c("#FA9A95","#C30000"))+theme(legend.position = "none",axis.title = element_blank(),axis.text.x = element_blank())
p4 = VlnPlot(srt_filter_cc_lpp,features=c("Ncf1"),pt.size=0.3,group.by="clp_lpp_gate")+scale_fill_manual(values = c("#FA9A95","#C30000"))+theme(legend.position = "none",axis.title = element_blank(),axis.text.x = element_blank())
p5 = VlnPlot(srt_filter_cc_lpp,features=c("Irf8"),pt.size=0.3,group.by="clp_lpp_gate")+scale_fill_manual(values = c("#FA9A95","#C30000"))+theme(legend.position = "none",axis.title = element_blank(),axis.text.x = element_blank())
p6 = VlnPlot(srt_filter_cc_lpp,features=c("Dntt"),pt.size=0.3,group.by="clp_lpp_gate")+scale_fill_manual(values = c("#FA9A95","#C30000"))+theme(legend.position = "none",axis.title = element_blank(),axis.text.x = element_blank())
p7 = VlnPlot(srt_filter_cc_lpp,features=c("Rag1"),pt.size=0.3,group.by="clp_lpp_gate")+scale_fill_manual(values = c("#FA9A95","#C30000"))+theme(legend.position = "none",axis.title = element_blank(),axis.text.x = element_blank())
p8 = VlnPlot(srt_filter_cc_lpp,features=c("Vpreb3"),pt.size=0.3,group.by="clp_lpp_gate")+scale_fill_manual(values = c("#FA9A95","#C30000"))+theme(legend.position = "none",axis.title = element_blank(),axis.text.x = element_blank())

ggarrange(p1,p2,p3,p4,p5,p6,p7,p8,ncol=2,nrow=4,hjust=T)
ggsave("figs/vln_plot_marker_LPPCLP.pdf",width = 5,height = 6)

table(srt_filter_cc_lpp@assays$integrated@scale.data["Rag1",srt_filter_cc_lpp$clp_lpp_gate=="LPP"]>1)[2]/sum(table(srt_filter_cc_lpp@assays$integrated@scale.data["Rag1",srt_filter_cc_lpp$clp_lpp_gate=="LPP"]>1))
      TRUE 
0.05533597 
table(srt_filter_cc_lpp@assays$integrated@scale.data["Rag1",srt_filter_cc_lpp$clp_lpp_gate=="CLP"]>1)[2]/sum(table(srt_filter_cc_lpp@assays$integrated@scale.data["Rag1",srt_filter_cc_lpp$clp_lpp_gate=="CLP"]>1))
TRUE 
 0.5 
srt_filter_cc_sel = srt_filter_cc

srt_filter_cc_sel = srt_filter_cc_sel[,srt_filter_cc_sel$seurat_clusters %in% c(1,6)]

DotPlot(srt_filter_cc_sel, features = c("Vpreb1","Blnk","Cd79a","Rag1","Pax5","Ly6d","Dntt","Irf8","Notch1","Plac8","Satb1","Il12a"), dot.scale = 8) + RotatedAxis()

srt_filter_cc.markers_sel = srt_filter_cc.markers[srt_filter_cc.markers$p_val_adj<0.001,]
srt_filter_cc.markers_sel$cluster = as.numeric(srt_filter_cc.markers_sel$cluster)
write.csv(srt_filter_cc.markers_sel,file = "scRNAseq_Seurat_markers.csv",row.names = FALSE)
table(srt_filter_cc$LPP_gate=="LPP",srt_filter_cc$seurat_clusters)
       
          0   1   2   3   4   5   6   7   8
  FALSE 364 105 229 234  33  33  26  15  21
  TRUE   38 163  29   2   2   0   5   9   2
table(srt_filter_cc$flt_gate=="flt3_high",srt_filter_cc$seurat_clusters)
       
          0   1   2   3   4   5   6   7   8
  FALSE 328  79 166 232  31  33  26  14  16
  TRUE   74 189  92   4   4   0   5  10   7
VennDiagram::venn.diagram(list(rownames(srt_filter_cc@meta.data)[srt_filter_cc$flt_gate=="flt3_high"],
                               rownames(srt_filter_cc@meta.data)[srt_filter_cc$seurat_clusters == 1]),
                          category.names = c("flt3_high","cluster2"),filename="venn_flthigh.tiff")
[1] 1
VennDiagram::venn.diagram(list(rownames(srt_filter_cc@meta.data)[srt_filter_cc$LPP_gate=="LPP"],
                               rownames(srt_filter_cc@meta.data)[srt_filter_cc$seurat_clusters == 1]),
                          category.names = c("LPP","cluster2"),filename="venn_LPP.tiff")
[1] 1
VennDiagram::venn.diagram(list(rownames(srt_filter_cc@meta.data)[srt_filter_cc$LMPP_gate=="LMPP"],
                               rownames(srt_filter_cc@meta.data)[srt_filter_cc$seurat_clusters == 1]),
                          category.names = c("LMPP","cluster2"),filename="venn_LMPP.tiff")
[1] 1
VennDiagram::venn.diagram(list(rownames(srt_filter_cc@meta.data)[srt_filter_cc$CLP_gate=="CLP"],
                               rownames(srt_filter_cc@meta.data)[srt_filter_cc$LPP_gate=="LPP"],
                               rownames(srt_filter_cc@meta.data)[srt_filter_cc$flt_gate=="flt3_high"],
                               rownames(srt_filter_cc@meta.data)[srt_filter_cc$LMPP_gate=="LMPP"],
                               rownames(srt_filter_cc@meta.data)[srt_filter_cc$seurat_clusters == 1]),
                          category.names = c("CLP","LPP","flt3_high","LMPP","cluster2"),filename="venn_all.tiff")
[1] 1
write.csv(rownames(srt_filter_cc@meta.data)[srt_filter_cc$CLP_gate=="CLP"],file = "CLP_cells.csv",quote = FALSE,row.names = FALSE)
write.csv(rownames(srt_filter_cc@meta.data)[srt_filter_cc$flt_gate=="flt3_high"],file = "flt3_high_cells.csv",quote = FALSE,row.names = FALSE)
write.csv(rownames(srt_filter_cc@meta.data)[srt_filter_cc$LPP_gate=="LPP"],file = "LPP_cells.csv",quote = FALSE,row.names = FALSE)
write.csv(rownames(srt_filter_cc@meta.data)[srt_filter_cc$LMPP_gate=="LMPP"],file = "LMPP_cells.csv",quote = FALSE,row.names = FALSE)

write.csv(rownames(srt_filter_cc@meta.data)[srt_filter_cc$seurat_clusters == 1],file = "CL2_cells.csv",quote = FALSE,row.names = FALSE)
CLP_c = rownames(srt_filter_cc@meta.data)[srt_filter_cc$CLP_gate=="CLP"]
flt3_c = rownames(srt_filter_cc@meta.data)[srt_filter_cc$flt_gate=="flt3_high"]
LPP_c = rownames(srt_filter_cc@meta.data)[srt_filter_cc$LPP_gate=="LPP"]
LMPP_c = rownames(srt_filter_cc@meta.data)[srt_filter_cc$LMPP_gate=="LMPP"]
cl2_c = rownames(srt_filter_cc@meta.data)[srt_filter_cc$seurat_clusters == 1]

cl2_in_others = c(sum(cl2_c %in% CLP_c),
                  sum(cl2_c %in% flt3_c),
                  sum(cl2_c %in% LPP_c),
                  sum(cl2_c %in% LMPP_c))

cl2_in_others
[1]  45 189 149 217
cl2_in_others/length(cl2_c)
[1] 0.1679104 0.7052239 0.5559701 0.8097015
cl2_in_others/c(length(CLP_c),
                length(flt3_c),
                length(LPP_c),
                length(LMPP_c))
[1] 0.5113636 0.4909091 0.5889328 0.2679012
plot(x,y)
text(x,y, c("CLP","FLT3_high","LPP","LMPP"),
     cex=0.65, pos=1,col="red") 

LS0tCnRpdGxlOiAiTk4xNzkiCm91dHB1dDogaHRtbF9ub3RlYm9vawotLS0KCgpgYGB7cn0KbGlicmFyeShzY1BpcGUpCmxpYnJhcnkoc2NhdGVyKQpsaWJyYXJ5KHNjcmFuKQpsaWJyYXJ5KGdncGxvdDIpCmxpYnJhcnkoU2V1cmF0KQpsaWJyYXJ5KGNvd3Bsb3QpCmxpYnJhcnkoZ2dwdWJyKQpsaWJyYXJ5KFJDb2xvckJyZXdlcikKbGlicmFyeShzY3RyYW5zZm9ybSkKbGlicmFyeShmbG93Q29yZSkKbGlicmFyeShwaGVhdG1hcCkKbGlicmFyeShkcGx5cikKbGlicmFyeShyZWFkcikKbGlicmFyeShnZ3JlcGVsKQpgYGAKCgoKCmBgYHtyfQpnZW5lX2ZpbHRlciA9IGZ1bmN0aW9uKHNjZSl7CiAga2VlcDEgPSAoYXBwbHkoY291bnRzKHNjZSksIDEsIGZ1bmN0aW9uKHgpIG1lYW4oeFt4PjBdKSkgPiAxLjEpICAjIGF2ZXJhZ2UgY291bnQgbGFyZ2VyIHRoYW4gMS4xCiAga2VlcDIgPSAocm93U3Vtcyhjb3VudHMoc2NlKT4wKSA+IDUpICMgZXhwcmVzc2VkIGluIG1vcmUgdGhhbiA1IGNlbGxzCiAgc2NlID0gc2NlWyhrZWVwMSAmIGtlZXAyKSwgXQogIHJldHVybihzY2UpCn0Kc2NyYW5fbm9ybSA9IGZ1bmN0aW9uKHNjZSl7CiAgc2NlID0gY29tcHV0ZVN1bUZhY3RvcnMoc2NlKQogIHNjZSA9IG5vcm1hbGl6ZShzY2UpCiAgcmV0dXJuKHNjZSkKfQpzY3Jhbl9oaWdoX3ZhciA9IGZ1bmN0aW9uKHNjZSx0b3BuPTMwMDApewogIHZhci5maXQgPC0gdHJlbmRWYXIoc2NlLCBtZXRob2Q9ImxvZXNzIiwgdXNlLnNwaWtlcz1GQUxTRSkKICB2YXIub3V0IDwtIGRlY29tcG9zZVZhcihzY2UsIHZhci5maXQpCiAgaHZnLm91dCA8LSB2YXIub3V0W29yZGVyKHZhci5vdXQkYmlvLCBkZWNyZWFzaW5nPVRSVUUpWzE6dG9wbl0sIF0KICByb3dEYXRhKHNjZSkkaGlfdmFyID0gRkFMU0UKICByb3dEYXRhKHNjZSkkaGlfdmFyW3Jvd25hbWVzKHJvd0RhdGEoc2NlKSkgJWluJSByb3duYW1lcyhodmcub3V0KV0gPSBUUlVFCiAgcmV0dXJuKHNjZSkKfQpgYGAKCgpgYGB7cn0Kc2NlX1JQSTQgPSBjcmVhdGVfc2NlX2J5X2RpcihkYXRhZGlyPSIvVXNlcnMvdGlhbi5sL0Ryb3Bib3gvcmVzZWFyY2gvRGFjaDFfcGFwZXIvTk4xNzkvUlBJNCIsb3JnYW5pc209Im1tdXNjdWx1c19nZW5lX2Vuc2VtYmwiLGdlbmVfaWRfdHlwZT0iZW5zZW1ibF9nZW5lX2lkIikKc2NlX1JQSTYgPSBjcmVhdGVfc2NlX2J5X2RpcihkYXRhZGlyPSIvVXNlcnMvdGlhbi5sL0Ryb3Bib3gvcmVzZWFyY2gvRGFjaDFfcGFwZXIvTk4xNzkvUlBJNiIsb3JnYW5pc209Im1tdXNjdWx1c19nZW5lX2Vuc2VtYmwiLGdlbmVfaWRfdHlwZT0iZW5zZW1ibF9nZW5lX2lkIikKc2NlX1JQSTcgPSBjcmVhdGVfc2NlX2J5X2RpcihkYXRhZGlyPSIvVXNlcnMvdGlhbi5sL0Ryb3Bib3gvcmVzZWFyY2gvRGFjaDFfcGFwZXIvTk4xNzkvUlBJNyIsb3JnYW5pc209Im1tdXNjdWx1c19nZW5lX2Vuc2VtYmwiLGdlbmVfaWRfdHlwZT0iZW5zZW1ibF9nZW5lX2lkIikKc2NlX1JQSTggPSBjcmVhdGVfc2NlX2J5X2RpcihkYXRhZGlyPSIvVXNlcnMvdGlhbi5sL0Ryb3Bib3gvcmVzZWFyY2gvRGFjaDFfcGFwZXIvTk4xNzkvUlBJOCIsb3JnYW5pc209Im1tdXNjdWx1c19nZW5lX2Vuc2VtYmwiLGdlbmVfaWRfdHlwZT0iZW5zZW1ibF9nZW5lX2lkIikKYGBgCgoKCmBgYHtyfQpzY2VfUlBJNCA9IGNhbGN1bGF0ZV9RQ19tZXRyaWNzKHNjZV9SUEk0KQpzY2VfUlBJNiA9IGNhbGN1bGF0ZV9RQ19tZXRyaWNzKHNjZV9SUEk2KQpzY2VfUlBJNyA9IGNhbGN1bGF0ZV9RQ19tZXRyaWNzKHNjZV9SUEk3KQpzY2VfUlBJOCA9IGNhbGN1bGF0ZV9RQ19tZXRyaWNzKHNjZV9SUEk4KQpgYGAKCgpgYGB7cn0Kc2NlX1JQSTRfcWMgPSBkZXRlY3Rfb3V0bGllcihzY2VfUlBJNCxjb21wID0gMikKc2NlX1JQSTZfcWMgPSBkZXRlY3Rfb3V0bGllcihzY2VfUlBJNixjb21wID0gMikKc2NlX1JQSTdfcWMgPSBkZXRlY3Rfb3V0bGllcihzY2VfUlBJNyxjb21wID0gMikKc2NlX1JQSThfcWMgPSBkZXRlY3Rfb3V0bGllcihzY2VfUlBJOCxjb21wID0gMikKCnNjZV9SUEk0X3FjID0gcmVtb3ZlX291dGxpZXJzKHNjZV9SUEk0X3FjKQpzY2VfUlBJNl9xYyA9IHJlbW92ZV9vdXRsaWVycyhzY2VfUlBJNl9xYykKc2NlX1JQSTdfcWMgPSByZW1vdmVfb3V0bGllcnMoc2NlX1JQSTdfcWMpCnNjZV9SUEk4X3FjID0gcmVtb3ZlX291dGxpZXJzKHNjZV9SUEk4X3FjKQoKc2NlX1JQSTRfcWMgPSBnZW5lX2ZpbHRlcihzY2VfUlBJNF9xYykKc2NlX1JQSTZfcWMgPSBnZW5lX2ZpbHRlcihzY2VfUlBJNl9xYykKc2NlX1JQSTdfcWMgPSBnZW5lX2ZpbHRlcihzY2VfUlBJN19xYykKc2NlX1JQSThfcWMgPSBnZW5lX2ZpbHRlcihzY2VfUlBJOF9xYykKCmNvbW1fZ2VuZXMgPSBSZWR1Y2UoaW50ZXJzZWN0LGxpc3Qocm93bmFtZXMoc2NlX1JQSTRfcWMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKHNjZV9SUEk2X3FjKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3duYW1lcyhzY2VfUlBJN19xYyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoc2NlX1JQSThfcWMpKSkKc2NlX1JQSTRfcWMgPSBjb252ZXJ0X2dlbmVpZChzY2VfUlBJNF9xYykKc2NlX1JQSTZfcWMgPSBjb252ZXJ0X2dlbmVpZChzY2VfUlBJNl9xYykKc2NlX1JQSTdfcWMgPSBjb252ZXJ0X2dlbmVpZChzY2VfUlBJN19xYykKc2NlX1JQSThfcWMgPSBjb252ZXJ0X2dlbmVpZChzY2VfUlBJOF9xYykKCmNvbW1fZ2VuZXMgPSBSZWR1Y2UoaW50ZXJzZWN0LGxpc3Qocm93bmFtZXMoc2NlX1JQSTRfcWMpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKHNjZV9SUEk2X3FjKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3duYW1lcyhzY2VfUlBJN19xYyksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoc2NlX1JQSThfcWMpKSkKCmNvbW1fZ2VuZXMgPSBjb21tX2dlbmVzWyFncmVwbCgiRU5TTVVTRyIsY29tbV9nZW5lcyldCmNvbW1fZ2VuZXMgPSBjb21tX2dlbmVzWyFncmVwbCgiRVJDQyIsY29tbV9nZW5lcyldCmNvbW1fZ2VuZXMgPSBjb21tX2dlbmVzWyFncmVwbCgiUmlrIixjb21tX2dlbmVzKV0KY29tbV9nZW5lcyA9IGNvbW1fZ2VuZXNbIWdyZXBsKCJIaXN0Iixjb21tX2dlbmVzKV0KY29tbV9nZW5lcyA9IGNvbW1fZ2VuZXNbIWdyZXBsKCJeUnBsIixjb21tX2dlbmVzKV0KY29tbV9nZW5lcyA9IGNvbW1fZ2VuZXNbIWdyZXBsKCJeUnBzIixjb21tX2dlbmVzKV0KY29tbV9nZW5lcyA9IGNvbW1fZ2VuZXNbIWdyZXBsKCJeSDJhYyIsY29tbV9nZW5lcyldCmNvbW1fZ2VuZXMgPSBjb21tX2dlbmVzWyFncmVwbCgiXkdtIixjb21tX2dlbmVzKV0KY29tbV9nZW5lcyA9IGNvbW1fZ2VuZXNbIWdyZXBsKCJebXQtIixjb21tX2dlbmVzKV0KCnNjZV9SUEk0X3FjID0gc2NlX1JQSTRfcWNbY29tbV9nZW5lcyxdCnNjZV9SUEk2X3FjID0gc2NlX1JQSTZfcWNbY29tbV9nZW5lcyxdCnNjZV9SUEk3X3FjID0gc2NlX1JQSTdfcWNbY29tbV9nZW5lcyxdCnNjZV9SUEk4X3FjID0gc2NlX1JQSThfcWNbY29tbV9nZW5lcyxdCgpjb2xuYW1lcyhzY2VfUlBJNF9xYykgPSBwYXN0ZSgiUlBJNCIsY29sbmFtZXMoc2NlX1JQSTRfcWMpLHNlcD0iXyIpCmNvbG5hbWVzKHNjZV9SUEk2X3FjKSA9IHBhc3RlKCJSUEk2Iixjb2xuYW1lcyhzY2VfUlBJNl9xYyksc2VwPSJfIikKY29sbmFtZXMoc2NlX1JQSTdfcWMpID0gcGFzdGUoIlJQSTciLGNvbG5hbWVzKHNjZV9SUEk3X3FjKSxzZXA9Il8iKQpjb2xuYW1lcyhzY2VfUlBJOF9xYykgPSBwYXN0ZSgiUlBJOCIsY29sbmFtZXMoc2NlX1JQSThfcWMpLHNlcD0iXyIpCnNjZV9SUEk0X3FjJGJhdGNoID0gIlJQSTQiCnNjZV9SUEk2X3FjJGJhdGNoID0gIlJQSTYiCnNjZV9SUEk3X3FjJGJhdGNoID0gIlJQSTciCnNjZV9SUEk4X3FjJGJhdGNoID0gIlJQSTgiCmBgYAoKYGBge3J9CnNjZV9SUEk0X3FjID0gbG9nTm9ybUNvdW50cyhzY2VfUlBJNF9xYykKc2NlX1JQSTZfcWMgPSBsb2dOb3JtQ291bnRzKHNjZV9SUEk2X3FjKQpzY2VfUlBJN19xYyA9IGxvZ05vcm1Db3VudHMoc2NlX1JQSTdfcWMpCnNjZV9SUEk4X3FjID0gbG9nTm9ybUNvdW50cyhzY2VfUlBJOF9xYykKYGBgCgoKYGBge3J9CmxpYnJhcnkoU2luZ2xlUikKcmVmLnNlIDwtIEltbUdlbkRhdGEoKQoKcHJlZC5SUEk0IDwtIFNpbmdsZVIodGVzdD1zY2VfUlBJNF9xYywgcmVmPXJlZi5zZSwgbGFiZWxzPXJlZi5zZSRsYWJlbC5maW5lKQpwcmVkLlJQSTYgPC0gU2luZ2xlUih0ZXN0PXNjZV9SUEk2X3FjLCByZWY9cmVmLnNlLCBsYWJlbHM9cmVmLnNlJGxhYmVsLmZpbmUpCnByZWQuUlBJNyA8LSBTaW5nbGVSKHRlc3Q9c2NlX1JQSTdfcWMsIHJlZj1yZWYuc2UsIGxhYmVscz1yZWYuc2UkbGFiZWwuZmluZSkKcHJlZC5SUEk4IDwtIFNpbmdsZVIodGVzdD1zY2VfUlBJOF9xYywgcmVmPXJlZi5zZSwgbGFiZWxzPXJlZi5zZSRsYWJlbC5maW5lKQpgYGAKCmBgYHtyfQp0bXBfdCA9IHRhYmxlKGMocHJlZC5SUEk0JHBydW5lZC5sYWJlbHMsIHByZWQuUlBJNiRwcnVuZWQubGFiZWxzLCBwcmVkLlJQSTckcHJ1bmVkLmxhYmVscywgcHJlZC5SUEk4JHBydW5lZC5sYWJlbHMpKQp0bXBfdFt0bXBfdD4xMF0KYGBgCgpgYGB7cn0KI2tlcHRfY2VsbHR5cGUgPSBjKCJCIGNlbGxzIChwcm9CLkNMUCkiLCJUIGNlbGxzIChULkVUUCkiLCJTdGVtIGNlbGxzIChNTFApIiwiU3RlbSBjZWxscyAoU0MuU1RTTCkiLCJTdGVtIGNlbGxzIChTQy5NUFAzNEYpIiwiU3RlbSBjZWxscyAoU0MuTFQzNEYpIiwiU3RlbSBjZWxscyAoU0MuQ01QLkRSKSIsIlN0ZW0gY2VsbHMgKEdNUCkiLCJTdGVtIGNlbGxzIChTQy5DRFApIikKa2VwdF9jZWxsdHlwZSA9IGNvbG5hbWVzKHByZWQuUlBJNCRzY29yZXMpCmNvbWJfc2NvcmVzID0gcmJpbmQocHJlZC5SUEk0JHNjb3Jlc1ssa2VwdF9jZWxsdHlwZV0sCiAgICAgICAgICAgICAgICAgICAgcHJlZC5SUEk2JHNjb3Jlc1ssa2VwdF9jZWxsdHlwZV0sCiAgICAgICAgICAgICAgICAgICAgcHJlZC5SUEk3JHNjb3Jlc1ssa2VwdF9jZWxsdHlwZV0sCiAgICAgICAgICAgICAgICAgICAgcHJlZC5SUEk4JHNjb3Jlc1ssa2VwdF9jZWxsdHlwZV0pCnJvd25hbWVzKGNvbWJfc2NvcmVzKSA9IGMocm93bmFtZXMocHJlZC5SUEk0KSwgcm93bmFtZXMocHJlZC5SUEk2KSwgcm93bmFtZXMocHJlZC5SUEk3KSwgcm93bmFtZXMocHJlZC5SUEk4KSkKYGBgCgoKCmBgYHtyfQpDMDg0X05haWtfU2FyYVRvbWVpX05OMTc5X1NlcVByaW1lcl9sYXlvdXRfSmFuMjBfU1RfIDwtcmVhZHhsOjpyZWFkX2V4Y2VsKCJ+L0Ryb3Bib3gvcmVzZWFyY2gvRGFjaDFfcGFwZXIvTk4xNzkvQzA4NF9OYWlrX1NhcmFUb21laV9OTjE3OV9TZXFQcmltZXIgbGF5b3V0X0phbjIwKFNUKS54bHN4Iiwgc2hlZXQgPSAiU2FtcGxlICYgSW5kZXgiLCBza2lwID0gMykKCkZBQ1NfYW5ubyA9IEMwODRfTmFpa19TYXJhVG9tZWlfTk4xNzlfU2VxUHJpbWVyX2xheW91dF9KYW4yMF9TVF9bLGMoIldlbGwgcG9zaXRpb24iLCIoc2VwYXJhdGUgaW5kZXggcmVhZCkuLi43IiwiPFI2NjAvMjAtQT46IGNLaXQgQVBDIiwiPFY0NTAvNTAtQT46IFBJUi1BIFBCIiwiPFY2NjAvMjAtQT46IElMN1IgQlY2NTAiLCI8Ujc4MC82MC1BPjogQ0Q0OCBBUEMgQ3k3IiwiPEI2OTUvNDAtQT46IENEMTFiIEJCNzAwIiwiPFk3ODAvNjAtQT46IENEMTUwIFBFIEN5NyIsIjxZNjcwLzE0LUE+OiBQSSIsIjxZNjEwLzIwLUE+OiBTY2ExIEE1OTQiLCI8QjUzMC8zMC1BPjogRGFjaDEgR0ZQIiwiPFY2MTAvMjAtQT46IENEMTYvMzIgQlY2MDUiLCI8WTU4Mi8xNS1BPjogRmx0MyBQRSIpXQpGQUNTX2Fubm8gPSBGQUNTX2Fubm9bIWlzLm5hKEZBQ1NfYW5ubyRgPFY0NTAvNTAtQT46IFBJUi1BIFBCYCksXQpGQUNTX2Fubm8kYChzZXBhcmF0ZSBpbmRleCByZWFkKS4uLjdgID0gZ3N1YigiICIsICIiLCBGQUNTX2Fubm8kYChzZXBhcmF0ZSBpbmRleCByZWFkKS4uLjdgLCBmaXhlZCA9IFRSVUUpCkZBQ1NfYW5ubyRjZWxsX2lkID0gcGFzdGUoRkFDU19hbm5vJGAoc2VwYXJhdGUgaW5kZXggcmVhZCkuLi43YCxGQUNTX2Fubm8kYFdlbGwgcG9zaXRpb25gLHNlcD0iXyIpCkZBQ1NfYW5ubyA9IEZBQ1NfYW5ub1shaXMubmEoRkFDU19hbm5vJGA8QjUzMC8zMC1BPjogRGFjaDEgR0ZQYCksXQpgYGAKCmBgYHtyfQpiaWV4cCAgPC0gYmlleHBvbmVudGlhbFRyYW5zZm9ybSgibXlUcmFuc2Zvcm0iLGE9MTAwLGM9NTAwMCkKbG9nZiA9IGZ1bmN0aW9uKHgpewogICAgeFt4PDEwMF09MTAwCiAgICByZXR1cm4obG9nMTAoeCsxKSkKfQoKCgpGQUNTX2Fubm9bLGMoIjxSNjYwLzIwLUE+OiBjS2l0IEFQQyIsIjxWNDUwLzUwLUE+OiBQSVItQSBQQiIsIjxWNjYwLzIwLUE+OiBJTDdSIEJWNjUwIiwiPFI3ODAvNjAtQT46IENENDggQVBDIEN5NyIsIjxCNjk1LzQwLUE+OiBDRDExYiBCQjcwMCIsIjxZNzgwLzYwLUE+OiBDRDE1MCBQRSBDeTciLCI8WTY3MC8xNC1BPjogUEkiLCI8WTYxMC8yMC1BPjogU2NhMSBBNTk0IiwiPEI1MzAvMzAtQT46IERhY2gxIEdGUCIsIjxWNjEwLzIwLUE+OiBDRDE2LzMyIEJWNjA1IiwiPFk1ODIvMTUtQT46IEZsdDMgUEUiKV0gPSBhcHBseShGQUNTX2Fubm9bLGMoIjxSNjYwLzIwLUE+OiBjS2l0IEFQQyIsIjxWNDUwLzUwLUE+OiBQSVItQSBQQiIsIjxWNjYwLzIwLUE+OiBJTDdSIEJWNjUwIiwiPFI3ODAvNjAtQT46IENENDggQVBDIEN5NyIsIjxCNjk1LzQwLUE+OiBDRDExYiBCQjcwMCIsIjxZNzgwLzYwLUE+OiBDRDE1MCBQRSBDeTciLCI8WTY3MC8xNC1BPjogUEkiLCI8WTYxMC8yMC1BPjogU2NhMSBBNTk0IiwiPEI1MzAvMzAtQT46IERhY2gxIEdGUCIsIjxWNjEwLzIwLUE+OiBDRDE2LzMyIEJWNjA1IiwiPFk1ODIvMTUtQT46IEZsdDMgUEUiKV0sIDIsIGZ1bmN0aW9uKHgpe2xvZ2YoeCl9KQoKcGxvdChGQUNTX2Fubm8kYDxZNTgyLzE1LUE+OiBGbHQzIFBFYCxGQUNTX2Fubm8kYDxZNzgwLzYwLUE+OiBDRDE1MCBQRSBDeTdgKQoKcGxvdChGQUNTX2Fubm8kYDxZNTgyLzE1LUE+OiBGbHQzIFBFYCxGQUNTX2Fubm8kYDxCNTMwLzMwLUE+OiBEYWNoMSBHRlBgKQpgYGAKCgpgYGB7cix3YXJuaW5nPUZBTFNFLG1lc3NhZ2U9RkFMU0UscmVzdWx0cz0naGlkZSd9CnNydDQgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IGNvdW50cyhzY2VfUlBJNF9xYyksbWV0YS5kYXRhPWFzLmRhdGEuZnJhbWUoY29sRGF0YShzY2VfUlBJNF9xYykpKQpzcnQ0IDwtIFNDVHJhbnNmb3JtKG9iamVjdCA9IHNydDQsIHZhcmlhYmxlLmZlYXR1cmVzLm49MjAwMCwgdmVyYm9zZSA9IEZBTFNFKQoKc3J0NiA8LSBDcmVhdGVTZXVyYXRPYmplY3QoY291bnRzID0gY291bnRzKHNjZV9SUEk2X3FjKSxtZXRhLmRhdGE9YXMuZGF0YS5mcmFtZShjb2xEYXRhKHNjZV9SUEk2X3FjKSkpCnNydDYgPC0gU0NUcmFuc2Zvcm0ob2JqZWN0ID0gc3J0NiwgdmFyaWFibGUuZmVhdHVyZXMubj0yMDAwLHZlcmJvc2UgPSBGQUxTRSkKCnNydDcgPC0gQ3JlYXRlU2V1cmF0T2JqZWN0KGNvdW50cyA9IGNvdW50cyhzY2VfUlBJN19xYyksbWV0YS5kYXRhPWFzLmRhdGEuZnJhbWUoY29sRGF0YShzY2VfUlBJN19xYykpKQpzcnQ3IDwtIFNDVHJhbnNmb3JtKG9iamVjdCA9IHNydDcsIHZhcmlhYmxlLmZlYXR1cmVzLm49MjAwMCx2ZXJib3NlID0gRkFMU0UpCgpzcnQ4IDwtIENyZWF0ZVNldXJhdE9iamVjdChjb3VudHMgPSBjb3VudHMoc2NlX1JQSThfcWMpLG1ldGEuZGF0YT1hcy5kYXRhLmZyYW1lKGNvbERhdGEoc2NlX1JQSThfcWMpKSkKc3J0OCA8LSBTQ1RyYW5zZm9ybShvYmplY3QgPSBzcnQ4LCB2YXJpYWJsZS5mZWF0dXJlcy5uPTIwMDAsdmVyYm9zZSA9IEZBTFNFKQoKb3B0aW9ucyhmdXR1cmUuZ2xvYmFscy5tYXhTaXplID0gMjEwMCAqIDEwMjReMikKaW1tdW5lLmZlYXR1cmVzIDwtIFNlbGVjdEludGVncmF0aW9uRmVhdHVyZXMob2JqZWN0Lmxpc3QgPSBsaXN0KHNydDQsIHNydDYsIHNydDcsIHNydDgpLCBuZmVhdHVyZXMgPSAyMDAwLCB2ZXJib3NlID0gRkFMU0UpCmltbXVuZS5jb21iaW5lZCA8LSBQcmVwU0NUSW50ZWdyYXRpb24ob2JqZWN0Lmxpc3QgPSBsaXN0KHNydDQsIHNydDYsIHNydDcsIHNydDgpLCBhbmNob3IuZmVhdHVyZXMgPSBpbW11bmUuZmVhdHVyZXMsIHZlcmJvc2UgPSBGQUxTRSkKCmltbXVuZS5hbmNob3JzIDwtIEZpbmRJbnRlZ3JhdGlvbkFuY2hvcnMob2JqZWN0Lmxpc3QgPSBpbW11bmUuY29tYmluZWQsIG5vcm1hbGl6YXRpb24ubWV0aG9kID0gIlNDVCIsIAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGFuY2hvci5mZWF0dXJlcyA9IGltbXVuZS5mZWF0dXJlcywgdmVyYm9zZSA9IEZBTFNFKQpzcnRfY29tYmluZSA8LSBJbnRlZ3JhdGVEYXRhKGFuY2hvcnNldCA9IGltbXVuZS5hbmNob3JzLCBub3JtYWxpemF0aW9uLm1ldGhvZCA9ICJTQ1QiLCBkaW1zID0gMToyMCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgdmVyYm9zZSA9IEZBTFNFKQpgYGAKCmBgYHtyLHdhcm5pbmc9RkFMU0UsbWVzc2FnZT1GQUxTRSxyZXN1bHRzPSdoaWRlJ30Kc3J0X2NvbWJpbmUgPC0gUnVuUENBKG9iamVjdCA9IHNydF9jb21iaW5lLCB2ZXJib3NlID0gRkFMU0UpCnNydF9jb21iaW5lIDwtIFJ1blVNQVAob2JqZWN0ID0gc3J0X2NvbWJpbmUsIGRpbXMgPSAxOjIwLCB2ZXJib3NlID0gRkFMU0UpCnNydF9jb21iaW5lIDwtIEZpbmROZWlnaGJvcnMob2JqZWN0ID0gc3J0X2NvbWJpbmUsIGRpbXMgPSAxOjIwLCB2ZXJib3NlID0gRkFMU0UpCnNydF9jb21iaW5lIDwtIEZpbmRDbHVzdGVycyhvYmplY3QgPSBzcnRfY29tYmluZSwgdmVyYm9zZSA9IEZBTFNFKQojIFZpc3VhbGl6YXRpb24KcDEgPC0gRGltUGxvdChzcnRfY29tYmluZSwgcmVkdWN0aW9uID0gInVtYXAiLCBncm91cC5ieSA9ICJiYXRjaCIpCnAyIDwtIERpbVBsb3Qoc3J0X2NvbWJpbmUsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBUUlVFKQpgYGAKCgpgYGB7cixmaWcud2lkdGg9MTAsZmlnLmhlaWdodD01fQpwbG90X2dyaWQocDEsIHAyKQpgYGAKCgpgYGB7cn0KRkFDU19hbm5vID0gYXMuZGF0YS5mcmFtZShGQUNTX2Fubm8pCkZBQ1NfYW5ubyA9IEZBQ1NfYW5ub1ttYXRjaChyb3duYW1lcyhzcnRfY29tYmluZUBtZXRhLmRhdGEpLEZBQ1NfYW5ubyRjZWxsX2lkKSxdCnNydF9jb21iaW5lQG1ldGEuZGF0YSA9IGNiaW5kKHNydF9jb21iaW5lQG1ldGEuZGF0YSwgRkFDU19hbm5vKQpzcnRfY29tYmluZSA9IHNydF9jb21iaW5lWywhaXMubmEoc3J0X2NvbWJpbmUkYDxCNTMwLzMwLUE+OiBEYWNoMSBHRlBgKV0KYGBgCgoKCgoKYGBge3IsZmlnLmhlaWdodD05LGZpZy53aWR0aD05fQpGZWF0dXJlUGxvdChzcnRfY29tYmluZSxmZWF0dXJlcyA9IGNvbG5hbWVzKHNydF9jb21iaW5lQG1ldGEuZGF0YSlbMjM6MzNdLHB0LnNpemU9MC4xLG1heC5jdXRvZmY9InE5NSIsbmNvbD0zKQpgYGAKCmBgYHtyfQpGZWF0dXJlUGxvdChzcnRfY29tYmluZSxmZWF0dXJlcyA9YygiUmFnMSIsIlJhZzIiLCJEbnR0IikscHQuc2l6ZT0wLjEsbWF4LmN1dG9mZj0icTk1IikKYGBgCgpgYGB7cn0Kc3J0X2NvbWJpbmUubWFya2VycyA8LSBGaW5kQWxsTWFya2VycyhzcnRfY29tYmluZSwgb25seS5wb3MgPSBUUlVFLHZlcmJvc2U9RkFMU0UpCmBgYAoKYGBge3IsZmlnLmhlaWdodD0xMixmaWcud2lkdGg9MTB9CnRvcDEwIDwtIHNydF9jb21iaW5lLm1hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSB0b3BfbihuID0gMTAsIHd0ID0gYXZnX2xvZ0ZDKQpEb0hlYXRtYXAoc3J0X2NvbWJpbmUsIGZlYXR1cmVzID0gdG9wMTAkZ2VuZSkKYGBgCgpgYGB7cn0Kcy5nZW5lcyA8LSB0b2xvd2VyKGNjLmdlbmVzJHMuZ2VuZXMpCmcybS5nZW5lcyA8LSB0b2xvd2VyKGNjLmdlbmVzJGcybS5nZW5lcykKc2ltcGxlQ2FwIDwtIGZ1bmN0aW9uKHgpIHsKICBwYXN0ZSh0b3VwcGVyKHN1YnN0cmluZyh4LCAxLDEpKSwgc3Vic3RyaW5nKHgsIDIpLAogICAgICBzZXA9IiIpCn0Kcy5nZW5lcyA9IHNpbXBsZUNhcChzLmdlbmVzKQpnMm0uZ2VuZXMgPSBzaW1wbGVDYXAoZzJtLmdlbmVzKQpgYGAKCmBgYHtyfQpzcnRfY29tYmluZSA8LSBDZWxsQ3ljbGVTY29yaW5nKHNydF9jb21iaW5lLCBzLmZlYXR1cmVzID0gcy5nZW5lcywgZzJtLmZlYXR1cmVzID0gZzJtLmdlbmVzLCBzZXQuaWRlbnQgPSBGQUxTRSkKc3J0X2NvbWJpbmUkQ0MuRGlmZmVyZW5jZSA8LSBzcnRfY29tYmluZSRTLlNjb3JlIC0gc3J0X2NvbWJpbmUkRzJNLlNjb3JlCmhlYWQoc3J0X2NvbWJpbmVbW11dKQpgYGAKCmBgYHtyfQpEaW1QbG90KHNydF9jb21iaW5lLCByZWR1Y3Rpb24gPSAidW1hcCIsIGdyb3VwLmJ5ID0gIlBoYXNlIikKYGBgCgpgYGB7cn0KI3NydF9maWx0ZXJfY2MgPC0gU2NhbGVEYXRhKHNydF9jb21iaW5lLCB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJDQy5EaWZmZXJlbmNlIiksIGZlYXR1cmVzID0gcm93bmFtZXMoc3J0X2NvbWJpbmUpLHZlcmJvc2UgPSBGQUxTRSkKc3J0X2ZpbHRlcl9jYyA8LSBTY2FsZURhdGEoc3J0X2NvbWJpbmUsICB2YXJzLnRvLnJlZ3Jlc3MgPSBjKCJTLlNjb3JlIiwgIkcyTS5TY29yZSIpLCBmZWF0dXJlcyA9IHJvd25hbWVzKHNydF9jb21iaW5lKSx2ZXJib3NlID0gRkFMU0UpCmBgYAoKYGBge3Isd2FybmluZz1GQUxTRSxtZXNzYWdlPUZBTFNFLHJlc3VsdHM9J2hpZGUnfQpzcnRfZmlsdGVyX2NjIDwtIFJ1blBDQShvYmplY3QgPSBzcnRfZmlsdGVyX2NjLCB2ZXJib3NlID0gRkFMU0UpCnNydF9maWx0ZXJfY2MgPC0gUnVuVU1BUChvYmplY3QgPSBzcnRfZmlsdGVyX2NjLCBkaW1zID0gMToyMCwgdmVyYm9zZSA9IEZBTFNFKQpzcnRfZmlsdGVyX2NjIDwtIEZpbmROZWlnaGJvcnMob2JqZWN0ID0gc3J0X2ZpbHRlcl9jYywgZGltcyA9IDE6MjAsIHZlcmJvc2UgPSBGQUxTRSkKc3J0X2ZpbHRlcl9jYyA8LSBGaW5kQ2x1c3RlcnMob2JqZWN0ID0gc3J0X2ZpbHRlcl9jYywgcmVzb2x1dGlvbiA9IDEuLCB2ZXJib3NlID0gRkFMU0UpCiMgVmlzdWFsaXphdGlvbgpwMSA8LSBEaW1QbG90KHNydF9maWx0ZXJfY2MsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgZ3JvdXAuYnkgPSAiUGhhc2UiKQpwMiA8LSBEaW1QbG90KHNydF9maWx0ZXJfY2MsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBUUlVFKQpgYGAKCgpgYGB7cixmaWcud2lkdGg9MTAsZmlnLmhlaWdodD01fQpwbG90X2dyaWQocDEsIHAyKQpgYGAKCgoKCmBgYHtyfQpzcnRfZmlsdGVyX2NjLm1hcmtlcnMgPC0gRmluZEFsbE1hcmtlcnMoc3J0X2ZpbHRlcl9jYywgb25seS5wb3MgPSBUUlVFLHZlcmJvc2U9RkFMU0UpCmBgYAoKYGBge3IsZmlnLmhlaWdodD05LGZpZy53aWR0aD04fQp0b3AxMCA8LSBzcnRfZmlsdGVyX2NjLm1hcmtlcnMgJT4lIGdyb3VwX2J5KGNsdXN0ZXIpICU+JSB0b3BfbihuID0gMTAsIHd0ID0gYXZnX2xvZ0ZDKQpEb0hlYXRtYXAoc3J0X2ZpbHRlcl9jYywgZmVhdHVyZXMgPSB0b3AxMCRnZW5lKQpgYGAKCmBgYHtyLGZpZy5oZWlnaHQ9NyxmaWcud2lkdGg9N30KRmVhdHVyZVBsb3Qoc3J0X2ZpbHRlcl9jYyxmZWF0dXJlcyA9IGNvbG5hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVsyMzozM10scHQuc2l6ZT0wLjUsbWF4LmN1dG9mZj0icTk1IixuY29sPTMpCmBgYAoKCmBgYHtyfQpnZ3Bsb3QoZGF0YT1OVUxMLGFlcyh4PWxvZzIoc3J0X2ZpbHRlcl9jYyRgPFk1ODIvMTUtQT46IEZsdDMgUEVgKSx5PWxvZzIoc3J0X2ZpbHRlcl9jYyRgPEI1MzAvMzAtQT46IERhY2gxIEdGUGApLGNvbD1hcy5mYWN0b3Ioc3J0X2ZpbHRlcl9jYyRzZXVyYXRfY2x1c3RlcnMpKSkrCiAgZ2VvbV9wb2ludCgpKwogIHNjYWxlX2NvbG9yX2JyZXdlcihwYWxldHRlID0gIlNldDEiKSsKICB0aGVtZV9idygpCmBgYAoKYGBge3J9Cm1rX2dlbmVzID0gdW5pcXVlKHNydF9maWx0ZXJfY2MubWFya2Vyc1tzcnRfZmlsdGVyX2NjLm1hcmtlcnMkcF92YWxfYWRqPDAuMDUsXSRnZW5lKQoKREVfZXhwciA9IHNydF9maWx0ZXJfY2NAYXNzYXlzJFNDVEBzY2FsZS5kYXRhW21rX2dlbmVzLF0KYGBgCgoKYGBge3J9CgpkYXRhYmFzZSA9ICJpbW1nZW4iCmltbWdlbl9zYW1wbGVzIDwtIHJlYWQuZGVsaW0ocGFzdGUwKCIvVXNlcnMvdGlhbi5sL0Ryb3Bib3gvcmVzZWFyY2gvRGFjaDFfcGFwZXIvcmVmX2RhdGEvIixkYXRhYmFzZSwiX3NhbXBsZXMudHh0IiksIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCmltbWdlbl9wcm9iZXMgPC0gcmVhZC5kZWxpbShwYXN0ZTAoIi9Vc2Vycy90aWFuLmwvRHJvcGJveC9yZXNlYXJjaC9EYWNoMV9wYXBlci9yZWZfZGF0YS8iLGRhdGFiYXNlLCJfcHJvYmVzLnR4dCIpLCBoZWFkZXI9RkFMU0UsIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCmltbWdlbl9leHByZXNzaW9uIDwtIHJlYWQuZGVsaW0ocGFzdGUwKCIvVXNlcnMvdGlhbi5sL0Ryb3Bib3gvcmVzZWFyY2gvRGFjaDFfcGFwZXIvcmVmX2RhdGEvIixkYXRhYmFzZSwiX2V4cHJlc3Npb24udHh0IiksIHN0cmluZ3NBc0ZhY3RvcnM9RkFMU0UpCgpsaWJyYXJ5KCdiaW9tYVJ0JykKbWFydCA8LSB1c2VEYXRhc2V0KCJtbXVzY3VsdXNfZ2VuZV9lbnNlbWJsIiwgdXNlTWFydCgiZW5zZW1ibCIpKQpHX2xpc3QgPC0gZ2V0Qk0oZmlsdGVycz0gImVuc2VtYmxfZ2VuZV9pZCIsIGF0dHJpYnV0ZXM9IGMoImVuc2VtYmxfZ2VuZV9pZCIsICJleHRlcm5hbF9nZW5lX25hbWUiLCAiZGVzY3JpcHRpb24iKSx2YWx1ZXM9aW1tZ2VuX3Byb2JlcyRWMiAsbWFydD1tYXJ0KQppbW1nZW5fcHJvYmVzID0gaW1tZ2VuX3Byb2Jlc1tpbW1nZW5fcHJvYmVzJFYyICVpbiUgR19saXN0JGVuc2VtYmxfZ2VuZV9pZCxdCkdfbGlzdCA9IEdfbGlzdFttYXRjaChpbW1nZW5fcHJvYmVzJFYyLCBHX2xpc3QkZW5zZW1ibF9nZW5lX2lkKSxdCmltbWdlbl9wcm9iZXMkZXh0ZXJuYWxfZ2VuZV9uYW1lID0gR19saXN0JGV4dGVybmFsX2dlbmVfbmFtZQoKaW1tZ2VuX2V4cHJlc3Npb24gPSBpbW1nZW5fZXhwcmVzc2lvbltpbW1nZW5fZXhwcmVzc2lvbiRwcm9iZUlkICVpbiUgaW1tZ2VuX3Byb2JlcyRWMSxdCmltbWdlbl9wcm9iZXMgPSBpbW1nZW5fcHJvYmVzW2ltbWdlbl9wcm9iZXMkVjEgJWluJSBpbW1nZW5fZXhwcmVzc2lvbiRwcm9iZUlkLF0KaW1tZ2VuX3Byb2JlcyA9IGltbWdlbl9wcm9iZXNbbWF0Y2goaW1tZ2VuX2V4cHJlc3Npb24kcHJvYmVJZCwgaW1tZ2VuX3Byb2JlcyRWMSksXQppbW1nZW5fZXhwcmVzc2lvbiRnZW5lX2lkID0gaW1tZ2VuX3Byb2JlcyRleHRlcm5hbF9nZW5lX25hbWUKaW1tZ2VuX2V4cHJlc3Npb24gPSBpbW1nZW5fZXhwcmVzc2lvblshZHVwbGljYXRlZChpbW1nZW5fZXhwcmVzc2lvbiRnZW5lX2lkKSxdCmdfaSA9IGltbWdlbl9leHByZXNzaW9uJGdlbmVfaWQKaW1tZ2VuX2V4cHJlc3Npb24gPSBpbW1nZW5fZXhwcmVzc2lvblssIShjb2xuYW1lcyhpbW1nZW5fZXhwcmVzc2lvbikgJWluJSBjKCJwcm9iZUlkIiwiZ2VuZV9pZCIpKV0KaW1tZ2VuX2V4cHJlc3Npb24gPSBhcy5tYXRyaXgoaW1tZ2VuX2V4cHJlc3Npb24pCnJvd25hbWVzKGltbWdlbl9leHByZXNzaW9uKSA9IGdfaQoKdGFibGUoaW1tZ2VuX3NhbXBsZXMkY2VsbF9saW5lYWdlKQppbW1nZW5fc2FtcGxlcyRzYW1wbGVJZCA9IGdzdWIoIi0iLCIuIixpbW1nZW5fc2FtcGxlcyRzYW1wbGVJZCkKI1NDX2xpc3QgPSBpbW1nZW5fc2FtcGxlc1tpbW1nZW5fc2FtcGxlcyRjZWxsX2xpbmVhZ2UgPT0gIlN0ZW0gQ2VsbHMiLCAic2FtcGxlSWQiXQoKU0NfbGlzdCA9IGMoIlNDX0NEUF9CTSIsIlNDX0NNUF9CTSIsIlNDX0dNUF9CTSIsCiAgICAgICAgICAgICJTQ19MVFNMX0JNIiwiU0NfTFRTTF9CTSIsIlNDX01EUF9CTSIsCiAgICAgICAgICAgICJTQ19NRVBfQk0iLCJTQ19NUFAzNEZfQk0iLCJTQ19TVDM0Rl9CTSIsCiAgICAgICAgICAgICJTQ19TVFNMX0JNIiwicHJlQl9GckRfQk0iLCJCMWJfUEMiKQojU0NfbGlzdCA9IGltbWdlbl9zYW1wbGVzJHNhbXBsZUlkCnN1Yl9pbW1nZW5fZXhwcmVzc2lvbiA9IGltbWdlbl9leHByZXNzaW9uW3Jvd25hbWVzKGltbWdlbl9leHByZXNzaW9uKSAlaW4lIHJvd25hbWVzKERFX2V4cHIpLCBjb2xuYW1lcyhpbW1nZW5fZXhwcmVzc2lvbikgJWluJSBTQ19saXN0XQpzdWJfaW1tZ2VuX2V4cHJlc3Npb24gPSBzdWJfaW1tZ2VuX2V4cHJlc3Npb25bIWR1cGxpY2F0ZWQocm93bmFtZXMoc3ViX2ltbWdlbl9leHByZXNzaW9uKSksXQpzdWJfREVfZXhwciA9IERFX2V4cHJbcm93bmFtZXMoREVfZXhwcikgJWluJSByb3duYW1lcyhzdWJfaW1tZ2VuX2V4cHJlc3Npb24pLF0Kc3ViX0RFX2V4cHIgPSBzdWJfREVfZXhwclshZHVwbGljYXRlZChyb3duYW1lcyhzdWJfREVfZXhwcikpLF0Kc3ViX0RFX2V4cHIgPSBzdWJfREVfZXhwcltvcmRlcihyb3duYW1lcyhzdWJfREVfZXhwcikpLF0Kc3ViX2ltbWdlbl9leHByZXNzaW9uID0gc3ViX2ltbWdlbl9leHByZXNzaW9uW29yZGVyKHJvd25hbWVzKHN1Yl9pbW1nZW5fZXhwcmVzc2lvbikpLF0KCgpwLnZhbF9tYXQgPSBjKCkKZm9yIChpIGluIDE6bmNvbChzdWJfaW1tZ2VuX2V4cHJlc3Npb24pKQp7CiAgcC52YWxfdmVjID0gYXBwbHkoc3ViX0RFX2V4cHIsIDIsIGZ1bmN0aW9uKHgpewogIGNvci50ZXN0KHgsc3ViX2ltbWdlbl9leHByZXNzaW9uWyxpXSwKICAgICAgICAgbWV0aG9kID0gInNwZWFybWFuIiwKICAgICAgICAgYWx0ZXJuYXRpdmUgPSAiZ3JlYXRlciIsZXhhY3Q9RkFMU0UpJHAudmFsdWV9KQogIHAudmFsX21hdCA9IHJiaW5kKHAudmFsX21hdCwtbG9nMTAocC52YWxfdmVjKSkKfQpyb3duYW1lcyhwLnZhbF9tYXQpID0gY29sbmFtZXMoc3ViX2ltbWdlbl9leHByZXNzaW9uKQoKIyBobV9pbW1nZW4gPSBoZWF0bWFwLjIocC52YWxfbWF0WyxvcmRlcihteWNsKV0sdHJhY2U9Im5vbmUiLAojICAgICAgICAgICBkZW5kcm9ncmFtPSJub25lIiwKIyAgICAgICAgICAgQ29sdj1GQUxTRSwKIyAgICAgICAgICAgY29sPWhtY29sLAojICAgICAgICAgICBzY2FsZT0iY29sdW1uIiwKIyAgICAgICAgICAgbGFiUm93ID0gIiIsCiMgICAgICAgICAgICNDb2xTaWRlQ29sb3JzID0gbXlDbHVzdGVyU2lkZUJhcltvcmRlcihteWNsKV0sCiMgICAgICAgICAgIGxhYkNvbCA9ICIiLAojICAgICAgICAgICBkZW5zaXR5LmluZm89Im5vbmUiLAojICAgICAgICAgICBrZXk9RkFMU0UpCgojcF9tYSA9IHAudmFsX21hdFssb3JkZXIobXljbCldCiNwX21hID0gcF9tYVtobV9pbW1nZW4kcm93SW5kLF0KCnAudmFsX21hdF9zID0gc2NhbGUocC52YWxfbWF0KQpwLnZhbF9tYXRfc1twLnZhbF9tYXRfcz4yXSA9IDIKcC52YWxfbWF0X3NbcC52YWxfbWF0X3M8KC0yKV0gPSAtMgoKcGhlYXRtYXAocC52YWxfbWF0X3NbLG9yZGVyKHNydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzKV0sY2x1c3Rlcl9jb2xzID0gRixzaG93X2NvbG5hbWVzID0gRixzY2FsZT0ibm9uZSIsYW5ub3RhdGlvbl9jb2wgPSBzcnRfZmlsdGVyX2NjQG1ldGEuZGF0YVssYygic2V1cmF0X2NsdXN0ZXJzIiwib3JpZy5pZGVudCIpXSxmaWxlbmFtZT0iZmlncy9pbW1nZW5fc2ltX2FsbC5wZGYiLHdpZHRoID0gMTAsaGVpZ2h0ID0gMjApCmBgYAoKYGBge3J9CmNvbWJfc2NvcmVzID0gY29tYl9zY29yZXNbY29sbmFtZXMoc3J0X2ZpbHRlcl9jYyksXQpjb21iX3Njb3JlcyA9IHNjYWxlKGNvbWJfc2NvcmVzKQpjb21iX3Njb3Jlc1tjb21iX3Njb3Jlcz4yLjVdID0gMi41CmNvbWJfc2NvcmVzW2NvbWJfc2NvcmVzPCgtMi41KV0gPSAtMi41CgpwaGVhdG1hcChjb21iX3Njb3Jlc1tvcmRlcihzcnRfZmlsdGVyX2NjJHNldXJhdF9jbHVzdGVycyksXSxzY2FsZSA9ICJub25lIixjbHVzdGVyX3Jvd3MgPSBGQUxTRSxzaG93X3Jvd25hbWVzID0gRkFMU0UsYW5ub3RhdGlvbl9yb3cgPSBzcnRfZmlsdGVyX2NjQG1ldGEuZGF0YVssYygic2V1cmF0X2NsdXN0ZXJzIiwiPFY2NjAvMjAtQT46IElMN1IgQlY2NTAiKV0sZm9udHNpemUgPSA2LGZpbGVuYW1lPSJmaWdzL2hlYXRtYXBfc2luZ2xlUl9zY29yZS5wZGYiLHdpZHRoID0gMjAsaGVpZ2h0ID0gMTApCmBgYAoKCgpgYGB7cn0KdG9wMTAgPC0gc3J0X2ZpbHRlcl9jYy5tYXJrZXJzICU+JSBncm91cF9ieShjbHVzdGVyKSAlPiUgdG9wX24obiA9IDEwLCB3dCA9IC1wX3ZhbF9hZGopCgp0b3BfZ2UgPSBjKCkKZm9yKGkgaW4gMDoobGVuZ3RoKHVuaXF1ZShzcnRfZmlsdGVyX2NjJHNldXJhdF9jbHVzdGVycykpLTEpKXsKICB0bXBfbWtfZGYgPSB0b3AxMFt0b3AxMCRjbHVzdGVyPT1pLF0KICB0bXBfbWtfZGYgPSB0bXBfbWtfZGZbb3JkZXIodG1wX21rX2RmJGF2Z19sb2dGQyxkZWNyZWFzaW5nID0gVFJVRSksXQogIGlmIChpICVpbiUgYygxLCA2KSl7CiAgICB0bXBfbWtfZGYgPSB0bXBfbWtfZGZbMTo2LF0KICB9ZWxzZXsKICAgIHRtcF9ta19kZiA9IHRtcF9ta19kZlsxOjMsXQogIH0KICB0b3BfZ2UgPSBjKHRvcF9nZSwgdG1wX21rX2RmJGdlbmUpCn0KdG9wX2dlID0gdG9wX2dlW3RvcF9nZSAlaW4lIHJvd25hbWVzKHNydF9maWx0ZXJfY2NAYXNzYXlzJGludGVncmF0ZWRAc2NhbGUuZGF0YSldCnRtcF9tYXQgPSBzcnRfZmlsdGVyX2NjQGFzc2F5cyRpbnRlZ3JhdGVkQHNjYWxlLmRhdGFbdG9wX2dlLF0KI3RtcF9tYXQgPSBzcnRfZmlsdGVyX2NjQGFzc2F5cyRTQ1RAc2NhbGUuZGF0YVt0b3BfZ2UsXQp0bXBfbWF0W3RtcF9tYXQ+Mi41XSA9IDIuNQp0bXBfbWF0W3RtcF9tYXQ8KC0yLjUpXSA9IC0yLjUKCmFubm9fZGYgPSBkYXRhLmZyYW1lKGNsdXN0ZXJzPXNydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzLAogICAgICAgICAgICAgICAgICAgICBEYWNoMUdGUD1zcnRfZmlsdGVyX2NjQG1ldGEuZGF0YVssIjxCNTMwLzMwLUE+OiBEYWNoMSBHRlAiXSwKICAgICAgICAgICAgICAgICAgICAgQ0QxNTA9c3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGFbLCI8WTc4MC82MC1BPjogQ0QxNTAgUEUgQ3k3Il0sCiAgICAgICAgICAgICAgICAgICAgIENEMTM1PXNydF9maWx0ZXJfY2NAbWV0YS5kYXRhWywiPFk1ODIvMTUtQT46IEZsdDMgUEUiXSwKICAgICAgICAgICAgICAgICAgICAgY0tpdD1zcnRfZmlsdGVyX2NjQG1ldGEuZGF0YVssIjxSNjYwLzIwLUE+OiBjS2l0IEFQQyJdLAogICAgICAgICAgICAgICAgICAgICBTY2ExPXNydF9maWx0ZXJfY2NAbWV0YS5kYXRhWywiPFk2MTAvMjAtQT46IFNjYTEgQTU5NCJdLAogICAgICAgICAgICAgICAgICAgICBDRDEyNz1zcnRfZmlsdGVyX2NjQG1ldGEuZGF0YVssIjxWNjYwLzIwLUE+OiBJTDdSIEJWNjUwIl0sCiAgICAgICAgICAgICAgICAgICAgIENENDg9c3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGFbLCI8Ujc4MC82MC1BPjogQ0Q0OCBBUEMgQ3k3Il0sCiAgICAgICAgICAgICAgICAgICAgIEJfY2VsbD1jb21iX3Njb3Jlc1ssIkIgY2VsbHMgKEIxYikiXSwKICAgICAgICAgICAgICAgICAgICAgQ0xQPWNvbWJfc2NvcmVzWywiQiBjZWxscyAocHJlQi5GckQpIl0sCiAgICAgICAgICAgICAgICAgICAgIEdNUD1jb21iX3Njb3Jlc1ssIlN0ZW0gY2VsbHMgKEdNUCkiXSwKICAgICAgICAgICAgICAgICAgICAgQ01QPWNvbWJfc2NvcmVzWywiU3RlbSBjZWxscyAoU0MuQ01QLkRSKSJdLAogICAgICAgICAgICAgICAgICAgICBMTVBQPWNvbWJfc2NvcmVzWywiU3RlbSBjZWxscyAoU0MuTVBQMzRGKSJdLAogICAgICAgICAgICAgICAgICAgICAjU1RTTD1jb21iX3Njb3Jlc1ssIlN0ZW0gY2VsbHMgKFNDLlNUU0wpIl0sCiAgICAgICAgICAgICAgICAgICAgIExUU0w9Y29tYl9zY29yZXNbLCJTdGVtIGNlbGxzIChTQy5MVDM0RikiXSxzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCgpnZXRQYWxldHRlID0gY29sb3JSYW1wUGFsZXR0ZShicmV3ZXIucGFsKDksICJTZXQxIikpCmNvbDkgPSBnZXRQYWxldHRlKDkpCgp0dHQgPSBjb2w5WzJdCmNvbDlbMl0gPSBjb2w5WzFdCmNvbDlbMV0gPSB0dHQKCm5hbWVzKGNvbDkpID0gYXMuY2hhcmFjdGVyKDA6OCkKYW5ub3RhdGlvbl9jb2xvcnMgPSBsaXN0KAogIGNsdXN0ZXJzPWNvbDksCiAgRGFjaDFHRlA9Qmx1ZUFuZFJlZCgpLAogIENEMTUwPUJsdWVBbmRSZWQoKSwKICBDRDEzNT1CbHVlQW5kUmVkKCksCiAgY0tpdD1CbHVlQW5kUmVkKCksIAogIENEMTI3PUJsdWVBbmRSZWQoKSwKICBTY2ExPUJsdWVBbmRSZWQoKVtmbG9vcig1MCoobWluKHNydF9maWx0ZXJfY2MkYDxZNjEwLzIwLUE+OiBTY2ExIEE1OTRgKS0wKS8obWF4KHNydF9maWx0ZXJfY2MkYDxZNjEwLzIwLUE+OiBTY2ExIEE1OTRgKS0wKSk6NTBdLCAgCiAgQ0Q0OD1CbHVlQW5kUmVkKCksCiAgR01QPUJsdWVBbmRSZWQoKSwKICBCX2NlbGw9Qmx1ZUFuZFJlZCgpLAogIENMUD1CbHVlQW5kUmVkKCksCiAgQ01QPUJsdWVBbmRSZWQoKSwKICBMTVBQPUJsdWVBbmRSZWQoKSwKICBTVFNMPUJsdWVBbmRSZWQoKSwKICBMVFNMPUJsdWVBbmRSZWQoKQopCgojaHRtcCA9IGhjbHVzdChkaXN0KGFubm9fZGZbLGMoIkJfY2VsbCIsIkNMUCIsIkNNUCIsIkxNUFAiLCJTVFNMIiwiTFRTTCIpXSkpCgpwaGVhdG1hcCh0bXBfbWF0WyxvcmRlcihzcnRfZmlsdGVyX2NjJHNldXJhdF9jbHVzdGVycyldLAogICAgICAgICBjbHVzdGVyX2NvbHMgPSBGQUxTRSwgCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IEZBTFNFLAogICAgICAgICBhbm5vdGF0aW9uX2NvbCA9IGFubm9fZGYsCiAgICAgICAgIGFubm90YXRpb25fY29sb3JzPWFubm90YXRpb25fY29sb3JzLAogICAgICAgICBzaG93X2NvbG5hbWVzID0gRkFMU0UsCiAgICAgICAgIGNvbG9yPVB1cnBsZUFuZFllbGxvdygpLAogICAgICAgICBmaWxlbmFtZT0iZmlncy9oZWF0bWFwX3dpdGhfU2V1cmF0X2NsdXN0ZXJfYWxsX21hcmtlcnMucGRmIix3aWR0aCA9IDcsaGVpZ2h0ID0gOC41KQoKCnBoZWF0bWFwKHRtcF9tYXRbLG9yZGVyKHNydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzKV0sCiAgICAgICAgIGNsdXN0ZXJfY29scyA9IEZBTFNFLCAKICAgICAgICAgY2x1c3Rlcl9yb3dzID0gRkFMU0UsCiAgICAgICAgIGFubm90YXRpb25fY29sID0gYW5ub19kZiwKICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnM9YW5ub3RhdGlvbl9jb2xvcnMsCiAgICAgICAgIHNob3dfY29sbmFtZXMgPSBGQUxTRSwKICAgICAgICAgY29sb3I9UHVycGxlQW5kWWVsbG93KCksCiAgICAgICAgIGZpbGVuYW1lPSJmaWdzL2hlYXRtYXBfd2l0aF9TZXVyYXRfY2x1c3Rlcl9hbGxfbWFya2Vyc19iaWcucGRmIix3aWR0aCA9IDcsaGVpZ2h0ID0gMjApCmBgYAoKCmBgYHtyfQpsaWJyYXJ5KHNsaW5nc2hvdCkKCgoKCnNkcyA8LSBzbGluZ3Nob3Qoc3J0X2ZpbHRlcl9jY0ByZWR1Y3Rpb25zJHVtYXBAY2VsbC5lbWJlZGRpbmdzLCBzcnRfZmlsdGVyX2NjJHNldXJhdF9jbHVzdGVycywgc3RhcnQuY2x1cz0zKQpgYGAKCmBgYHtyfQpwbG90KHNkc0BjdXJ2ZXMkY3VydmUzKQpgYGAKCgoKCmBgYHtyfQpzZHNAbGluZWFnZXMkTGluZWFnZTMKYGBgCgpgYGB7cn0KCmBgYAoKCmBgYHtyfQpvcmRlcl9kZiA9IHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhCm9yZGVyX2RmID0gb3JkZXJfZGZbc2RzQGN1cnZlcyRjdXJ2ZTMkb3JkLF0Kb3JkZXJfZGYgPSBvcmRlcl9kZltvcmRlcl9kZiRzZXVyYXRfY2x1c3RlcnMgJWluJSBzZHNAbGluZWFnZXMkTGluZWFnZTMsXQpvcmRlcl9kZl9yYXcgPSBvcmRlcl9kZgoKCgpwbG90KG9yZGVyX2RmX3JhdyRgPFY2NjAvMjAtQT46IElMN1IgQlY2NTBgLCBvcmRlcl9kZiRgPFY2NjAvMjAtQT46IElMN1IgQlY2NTBgKQpoaXN0KG9yZGVyX2RmJGA8VjY2MC8yMC1BPjogSUw3UiBCVjY1MGApCmBgYAoKCmBgYHtyfQpwbGlzdCA9IGxpc3QoKQpwbGlzdFtbMV1dID0gZ2dwbG90KGRhdGE9TlVMTCxhZXMoeD0xOm5yb3cob3JkZXJfZGYpLAogICAgICAgICAgICAgICAgICAgICB5PW9yZGVyX2RmJGA8VjY2MC8yMC1BPjogSUw3UiBCVjY1MGApKSsKICBsYWJzKHg9InBzZXVkb3RpbWUiLHk9IkNEMTI3IikrCiAgZ2VvbV9wb2ludChzaXplPTAuNSxhZXMoY29sPW9yZGVyX2RmJHNldXJhdF9jbHVzdGVycykpKwogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIGZvcm11bGEgPSB5IH4geCwgc2l6ZSA9IDEsc3Bhbj0uMykrCiAgdGhlbWVfYncoKQoKcGxpc3RbWzJdXSA9IGdncGxvdChkYXRhPU5VTEwsYWVzKHg9MTpucm93KG9yZGVyX2RmKSwKICAgICAgICAgICAgICAgICAgICAgeT1vcmRlcl9kZiRgPEI1MzAvMzAtQT46IERhY2gxIEdGUGApKSsKICBsYWJzKHg9InBzZXVkb3RpbWUiLHk9IkRhY2gxIikrCiAgZ2VvbV9wb2ludChzaXplPTAuNSxhZXMoY29sPW9yZGVyX2RmJHNldXJhdF9jbHVzdGVycykpKwogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIGZvcm11bGEgPSB5IH4geCwgc2l6ZSA9IDEsc3Bhbj0uNCkrCiAgdGhlbWVfYncoKQoKcGxpc3RbWzNdXSA9IGdncGxvdChkYXRhPU5VTEwsYWVzKHg9MTpucm93KG9yZGVyX2RmKSwKICAgICAgICAgICAgICAgICAgICAgeT1vcmRlcl9kZiRgPFk3ODAvNjAtQT46IENEMTUwIFBFIEN5N2ApKSsKICBsYWJzKHg9InBzZXVkb3RpbWUiLHk9IkNEMTUwIikrCiBnZW9tX3BvaW50KHNpemU9MC41LGFlcyhjb2w9b3JkZXJfZGYkc2V1cmF0X2NsdXN0ZXJzKSkrCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgZm9ybXVsYSA9IHkgfiB4LCBzaXplID0gMSxzcGFuPS4zKSsKICB0aGVtZV9idygpCgpwbGlzdFtbNF1dID0gZ2dwbG90KGRhdGE9TlVMTCxhZXMoeD0xOm5yb3cob3JkZXJfZGYpLAogICAgICAgICAgICAgICAgICAgICB5PW9yZGVyX2RmJGA8Ujc4MC82MC1BPjogQ0Q0OCBBUEMgQ3k3YCkpKwogIGxhYnMoeD0icHNldWRvdGltZSIseT0iQ0Q0OCIpKwogIGdlb21fcG9pbnQoc2l6ZT0wLjUsYWVzKGNvbD1vcmRlcl9kZiRzZXVyYXRfY2x1c3RlcnMpKSsKICBzdGF0X3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBmb3JtdWxhID0geSB+IHgsIHNpemUgPSAxLHNwYW49LjYpKwogIHRoZW1lX2J3KCkKCnBsaXN0W1s1XV0gPSBnZ3Bsb3QoZGF0YT1OVUxMLGFlcyh4PTE6bnJvdyhvcmRlcl9kZiksCiAgICAgICAgICAgICAgICAgICAgIHk9b3JkZXJfZGYkYDxSNjYwLzIwLUE+OiBjS2l0IEFQQ2ApKSsKICBsYWJzKHg9InBzZXVkb3RpbWUiLHk9ImNLaXQiKSsKICBnZW9tX3BvaW50KHNpemU9MC41LGFlcyhjb2w9b3JkZXJfZGYkc2V1cmF0X2NsdXN0ZXJzKSkrCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgZm9ybXVsYSA9IHkgfiB4LCBzaXplID0gMSxzcGFuPS41KSsKICB0aGVtZV9idygpCgpwbGlzdFtbNl1dID0gZ2dwbG90KGRhdGE9TlVMTCxhZXMoeD0xOm5yb3cob3JkZXJfZGYpLAogICAgICAgICAgICAgICAgICAgICB5PW9yZGVyX2RmJGA8WTYxMC8yMC1BPjogU2NhMSBBNTk0YCkpKwogIGxhYnMoeD0icHNldWRvdGltZSIseT0iU2NhMSIpKwogIGdlb21fcG9pbnQoc2l6ZT0wLjUsYWVzKGNvbD1vcmRlcl9kZiRzZXVyYXRfY2x1c3RlcnMpKSsKICBzdGF0X3Ntb290aChtZXRob2QgPSAibG9lc3MiLCBmb3JtdWxhID0geSB+IHgsIHNpemUgPSAxLHNwYW49LjYpKwogIHRoZW1lX2J3KCkKCnBsaXN0W1s3XV0gPSBnZ3Bsb3QoZGF0YT1OVUxMLGFlcyh4PTE6bnJvdyhvcmRlcl9kZiksCiAgICAgICAgICAgICAgICAgICAgIHk9b3JkZXJfZGYkYDxZNTgyLzE1LUE+OiBGbHQzIFBFYCkpKwogIGxhYnMoeD0icHNldWRvdGltZSIseT0iQ0QxMzUiKSsKICBnZW9tX3BvaW50KHNpemU9MC41LGFlcyhjb2w9b3JkZXJfZGYkc2V1cmF0X2NsdXN0ZXJzKSkrCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgZm9ybXVsYSA9IHkgfiB4LCBzaXplID0gMSxzcGFuPS43KSsKICB0aGVtZV9idygpCgpnZ2FycmFuZ2UocGxvdGxpc3QgPSBwbGlzdCxuY29sPTEsYWxpZ24gPSAiaCIsY29tbW9uLmxlZ2VuZCA9IFRSVUUpCmdnc2F2ZSgiZmlncy9wc2V1ZG90aW1lX0ZBQ1NfbWFya2VyLnBkZiIsd2lkdGg9NSxoZWlnaHQ9MTApCmBgYAoKYGBge3J9CnBsaXN0ID0gbGlzdCgpCgp0bXBfZXhwciA9IHNydF9maWx0ZXJfY2NAYXNzYXlzJGludGVncmF0ZWRAc2NhbGUuZGF0YVsiRG50dCIsc2RzQGN1cnZlcyRjdXJ2ZTMkb3JkW3NydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzICVpbiUgc2RzQGxpbmVhZ2VzJExpbmVhZ2UzXV0KdG1wX2V4cHJbdG1wX2V4cHI8cXVhbnRpbGUodG1wX2V4cHIsMC4wNSldID0gcXVhbnRpbGUodG1wX2V4cHIsMC4wNSkKdG1wX2RmID0gZGF0YS5mcmFtZSh0bXBfZXhwcj10bXBfZXhwcixzZXVyYXRfY2x1c3RlcnM9b3JkZXJfZGYkc2V1cmF0X2NsdXN0ZXJzLHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKdG1wX2RmJG1vdmVfbWVkID0gIHpvbzo6cm9sbGFwcGx5cih0bXBfZGYkdG1wX2V4cHIsRlVOID1tZWRpYW4sd2lkdGggPSAyMCxmaWxsPU5BKQpwbGlzdFtbMV1dID0gZ2dwbG90KGRhdGE9dG1wX2RmLGFlcyh4PTE6bnJvdyh0bXBfZGYpLAogICAgICAgICAgICAgICAgICAgICB5PXRtcF9leHByKSkrCiAgbGFicyhjb2w9IiIsdGl0bGU9IkRudHQiKSsKICBnZW9tX3BvaW50KHNpemU9MC41LGFlcyhjb2w9c2V1cmF0X2NsdXN0ZXJzKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbDkpKwogIHN0YXRfc21vb3RoKGFlcyh4PTE6bnJvdyh0bXBfZGYpLHk9bW92ZV9tZWQpLG1ldGhvZCA9ICJsb2VzcyIsIGZvcm11bGEgPSB5IH4geCwgc2l6ZSA9IDEsc3Bhbj0uMykrCiAgdGhlbWVfYncoKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSxwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLApwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpCgp0bXBfZXhwciA9IHNydF9maWx0ZXJfY2NAYXNzYXlzJGludGVncmF0ZWRAc2NhbGUuZGF0YVsiU2F0YjEiLHNkc0BjdXJ2ZXMkY3VydmUzJG9yZFtzcnRfZmlsdGVyX2NjJHNldXJhdF9jbHVzdGVycyAlaW4lIHNkc0BsaW5lYWdlcyRMaW5lYWdlM11dCnRtcF9leHByW3RtcF9leHByPHF1YW50aWxlKHRtcF9leHByLDAuMDUpXSA9IHF1YW50aWxlKHRtcF9leHByLDAuMDUpCnRtcF9kZiA9IGRhdGEuZnJhbWUodG1wX2V4cHI9dG1wX2V4cHIsc2V1cmF0X2NsdXN0ZXJzPW9yZGVyX2RmJHNldXJhdF9jbHVzdGVycyxzdHJpbmdzQXNGYWN0b3JzID0gRkFMU0UpCnRtcF9kZiRtb3ZlX21lZCA9ICB6b286OnJvbGxhcHBseXIodG1wX2RmJHRtcF9leHByLEZVTiA9bWVkaWFuLHdpZHRoID0gMTAsZmlsbD1OQSkKcGxpc3RbWzJdXSA9IGdncGxvdChkYXRhPXRtcF9kZixhZXMoeD0xOm5yb3codG1wX2RmKSwKICAgICAgICAgICAgICAgICAgICAgeT10bXBfZXhwcikpKwogIGxhYnMoY29sPSIiLHRpdGxlPSJTYXRiMSIpKwogIGdlb21fcG9pbnQoc2l6ZT0wLjUsYWVzKGNvbD1zZXVyYXRfY2x1c3RlcnMpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sOSkrCiAgc3RhdF9zbW9vdGgoYWVzKHg9MTpucm93KHRtcF9kZikseT1tb3ZlX21lZCksbWV0aG9kID0gImxvZXNzIiwgZm9ybXVsYSA9IHkgfiB4LCBzaXplID0gMSxzcGFuPS4zKSsKICB0aGVtZV9idygpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCnBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkKCnRtcF9leHByID0gc3J0X2ZpbHRlcl9jY0Bhc3NheXMkaW50ZWdyYXRlZEBzY2FsZS5kYXRhWyJOY2YxIixzZHNAY3VydmVzJGN1cnZlMyRvcmRbc3J0X2ZpbHRlcl9jYyRzZXVyYXRfY2x1c3RlcnMgJWluJSBzZHNAbGluZWFnZXMkTGluZWFnZTNdXQp0bXBfZXhwclt0bXBfZXhwcjxxdWFudGlsZSh0bXBfZXhwciwwLjA1KV0gPSBxdWFudGlsZSh0bXBfZXhwciwwLjA1KQp0bXBfZGYgPSBkYXRhLmZyYW1lKHRtcF9leHByPXRtcF9leHByLHNldXJhdF9jbHVzdGVycz1vcmRlcl9kZiRzZXVyYXRfY2x1c3RlcnMsc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpwbGlzdFtbM11dID0gZ2dwbG90KGRhdGE9dG1wX2RmLGFlcyh4PTE6bnJvdyh0bXBfZGYpLAogICAgICAgICAgICAgICAgICAgICB5PXRtcF9leHByKSkrCiAgbGFicyhjb2w9IiIsdGl0bGU9Ik5jZjEiKSsKICBnZW9tX3BvaW50KHNpemU9MC41LGFlcyhjb2w9c2V1cmF0X2NsdXN0ZXJzKSkrCiAgc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IGNvbDkpKwogIHN0YXRfc21vb3RoKG1ldGhvZCA9ICJsb2VzcyIsIGZvcm11bGEgPSB5IH4geCwgc2l6ZSA9IDEsc3Bhbj0uMykrCiAgdGhlbWVfYncoKSsKICB0aGVtZShwbG90LnRpdGxlID0gZWxlbWVudF90ZXh0KGhqdXN0ID0gMC41KSxwYW5lbC5ncmlkLm1ham9yID0gZWxlbWVudF9ibGFuaygpLCBwYW5lbC5ncmlkLm1pbm9yID0gZWxlbWVudF9ibGFuaygpLApwYW5lbC5iYWNrZ3JvdW5kID0gZWxlbWVudF9ibGFuaygpLCBheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGlja3MueCA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLmxpbmUgPSBlbGVtZW50X2xpbmUoY29sb3VyID0gImJsYWNrIikpCgp0bXBfZXhwciA9IHNydF9maWx0ZXJfY2NAYXNzYXlzJGludGVncmF0ZWRAc2NhbGUuZGF0YVsiVnByZWIxIixzZHNAY3VydmVzJGN1cnZlMyRvcmRbc3J0X2ZpbHRlcl9jYyRzZXVyYXRfY2x1c3RlcnMgJWluJSBzZHNAbGluZWFnZXMkTGluZWFnZTNdXQp0bXBfZXhwclt0bXBfZXhwcjxxdWFudGlsZSh0bXBfZXhwciwwLjA1KV0gPSBxdWFudGlsZSh0bXBfZXhwciwwLjA1KQp0bXBfZGYgPSBkYXRhLmZyYW1lKHRtcF9leHByPXRtcF9leHByLHNldXJhdF9jbHVzdGVycz1vcmRlcl9kZiRzZXVyYXRfY2x1c3RlcnMsc3RyaW5nc0FzRmFjdG9ycyA9IEZBTFNFKQpwbGlzdFtbNF1dID0gZ2dwbG90KGRhdGE9dG1wX2RmLGFlcyh4PTE6bnJvdyh0bXBfZGYpLAogICAgICAgICAgICAgICAgICAgICB5PXRtcF9leHByKSkrCiAgbGFicyhjb2w9IiIsdGl0bGU9IlZwcmViMSIpKwogIGdlb21fcG9pbnQoc2l6ZT0wLjUsYWVzKGNvbD1zZXVyYXRfY2x1c3RlcnMpKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gY29sOSkrCiAgc3RhdF9zbW9vdGgobWV0aG9kID0gImxvZXNzIiwgZm9ybXVsYSA9IHkgfiB4LCBzaXplID0gMSxzcGFuPS4zKSsKICB0aGVtZV9idygpKwogIHRoZW1lKHBsb3QudGl0bGUgPSBlbGVtZW50X3RleHQoaGp1c3QgPSAwLjUpLHBhbmVsLmdyaWQubWFqb3IgPSBlbGVtZW50X2JsYW5rKCksIHBhbmVsLmdyaWQubWlub3IgPSBlbGVtZW50X2JsYW5rKCksCnBhbmVsLmJhY2tncm91bmQgPSBlbGVtZW50X2JsYW5rKCksIGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCksYXhpcy50aWNrcy54ID0gZWxlbWVudF9ibGFuaygpLGF4aXMubGluZSA9IGVsZW1lbnRfbGluZShjb2xvdXIgPSAiYmxhY2siKSkKCgoKCmdnYXJyYW5nZShwbG90bGlzdCA9IHBsaXN0LG5jb2w9MSxhbGlnbiA9ICJoIixjb21tb24ubGVnZW5kID0gVFJVRSkKZ2dzYXZlKCJmaWdzL3BzZXVkb3RpbWVfbWFya2VyX2dlbmVzLnBkZiIsd2lkdGg9NSxoZWlnaHQ9MTApCmBgYAoKCmBgYHtyfQpEaW1QbG90KHNydF9maWx0ZXJfY2MsIHJlZHVjdGlvbiA9ICJ1bWFwIiwgbGFiZWwgPSBGQUxTRSxjb2xzID0gY29sOSkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLGxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQgID1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCmdnc2F2ZSgiZmlncy91bWFwX2NvbF9ieV9jbHVzdGVyLnBkZiIsd2lkdGggPSA0LjUsaGVpZ2h0ID0gNC41KQpgYGAKCgpgYGB7cn0KcGxvdChzcnRfZmlsdGVyX2NjJGA8WTc4MC82MC1BPjogQ0QxNTAgUEUgQ3k3YCxzcnRfZmlsdGVyX2NjJGA8Ujc4MC82MC1BPjogQ0Q0OCBBUEMgQ3k3YCkKYGBgCgpgYGB7cn0KcGxvdChzcnRfZmlsdGVyX2NjJGA8WTU4Mi8xNS1BPjogRmx0MyBQRWAsc3J0X2ZpbHRlcl9jYyRgPFI3ODAvNjAtQT46IENENDggQVBDIEN5N2ApCmBgYAoKYGBge3J9CnBsb3Qoc3J0X2ZpbHRlcl9jYyRgPFk1ODIvMTUtQT46IEZsdDMgUEVgICxzcnRfZmlsdGVyX2NjJGA8WTc4MC82MC1BPjogQ0QxNTAgUEUgQ3k3YCkKYGBgCgpgYGB7cn0KcGxvdChzcnRfZmlsdGVyX2NjJGA8WTU4Mi8xNS1BPjogRmx0MyBQRWAgLHNydF9maWx0ZXJfY2MkYDxCNTMwLzMwLUE+OiBEYWNoMSBHRlBgKQpgYGAKCmBgYHtyfQpwbG90KHNydF9maWx0ZXJfY2MkYDxWNjYwLzIwLUE+OiBJTDdSIEJWNjUwYCAsc3J0X2ZpbHRlcl9jYyRgPFk1ODIvMTUtQT46IEZsdDMgUEVgKQpgYGAKCmh0dHBzOi8vd3d3Lm5jYmkubmxtLm5paC5nb3YvcG1jL2FydGljbGVzL1BNQzQ1NDIxNTAvCgpgYGB7cn0KI0xULUhTQzogQ0QxMzUtICBDRDE1MCsgIENENDgtCmlzX0xUSFNDID0gKHNydF9maWx0ZXJfY2MkYDxZNTgyLzE1LUE+OiBGbHQzIFBFYDwzLjUpICYgKHNydF9maWx0ZXJfY2MkYDxZNzgwLzYwLUE+OiBDRDE1MCBQRSBDeTdgPjMuNSkgJiAoc3J0X2ZpbHRlcl9jYyRgPFI3ODAvNjAtQT46IENENDggQVBDIEN5N2A8My4zKQojU1QtSFNDOiBDRDEzNS0gIENEMTUwLSAgQ0Q0OC0KaXNfU1RIU0MgPSAoc3J0X2ZpbHRlcl9jYyRgPFk1ODIvMTUtQT46IEZsdDMgUEVgPDMuNSkgJiAoc3J0X2ZpbHRlcl9jYyRgPFk3ODAvNjAtQT46IENEMTUwIFBFIEN5N2A8My41KSAmIChzcnRfZmlsdGVyX2NjJGA8Ujc4MC82MC1BPjogQ0Q0OCBBUEMgQ3k3YDwzLjMpCiNNUFAyOiBDRDEzNS0gIENEMTUwKyAgQ0Q0OCsKaXNfTVBQMiA9IChzcnRfZmlsdGVyX2NjJGA8WTU4Mi8xNS1BPjogRmx0MyBQRWA8My41KSAmIChzcnRfZmlsdGVyX2NjJGA8WTc4MC82MC1BPjogQ0QxNTAgUEUgQ3k3YD4zLjUpICYgKHNydF9maWx0ZXJfY2MkYDxSNzgwLzYwLUE+OiBDRDQ4IEFQQyBDeTdgPjMuMykKI01QUDM6IENEMTM1LSAgQ0QxNTAtICBDRDQ4Kwppc19NUFAzID0gKHNydF9maWx0ZXJfY2MkYDxZNTgyLzE1LUE+OiBGbHQzIFBFYDwzLjUpICYgKHNydF9maWx0ZXJfY2MkYDxZNzgwLzYwLUE+OiBDRDE1MCBQRSBDeTdgPDMuNSkgJiAoc3J0X2ZpbHRlcl9jYyRgPFI3ODAvNjAtQT46IENENDggQVBDIEN5N2A+My4zKQppc19NUFA0ID0gKHNydF9maWx0ZXJfY2MkYDxZNTgyLzE1LUE+OiBGbHQzIFBFYD4zLjUpICYgKHNydF9maWx0ZXJfY2MkYDxZNzgwLzYwLUE+OiBDRDE1MCBQRSBDeTdgPDMuNSkgCmlzX0NMUCA9IHNydF9maWx0ZXJfY2MkYDxWNjYwLzIwLUE+OiBJTDdSIEJWNjUwYD4zCnNydF9maWx0ZXJfY2MkZ2F0ZSA9ICJNUFAyIgpzcnRfZmlsdGVyX2NjJGdhdGVbaXNfTFRIU0NdPSJMVC1IU0MiCnNydF9maWx0ZXJfY2MkZ2F0ZVtpc19TVEhTQ109IlNULUhTQyIKc3J0X2ZpbHRlcl9jYyRnYXRlW2lzX01QUDJdPSJNUFAyIgpzcnRfZmlsdGVyX2NjJGdhdGVbaXNfTVBQM109Ik1QUDMiCnNydF9maWx0ZXJfY2MkZ2F0ZVtpc19NUFA0XT0iTVBQNCIKc3J0X2ZpbHRlcl9jYyRnYXRlW2lzX0NMUF09IkNMUCIKCkRpbVBsb3Qoc3J0X2ZpbHRlcl9jYywgZ3JvdXAuYnkgPSAiZ2F0ZSIsIGxhYmVsID0gRkFMU0UpK3RoZW1lKGxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQgID1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCmBgYAoKYGBge3J9CnNydF9maWx0ZXJfY2MkRkFDU19DVCA9ICJMTVBQIgpzcnRfZmlsdGVyX2NjJEZBQ1NfQ1Rbc3J0X2ZpbHRlcl9jYyRgPFk3ODAvNjAtQT46IENEMTUwIFBFIEN5N2A+My41ICYgc3J0X2ZpbHRlcl9jYyRgPFk1ODIvMTUtQT46IEZsdDMgUEVgPDMuNV0gPSAiTFQgKyBNUFAyIgpzcnRfZmlsdGVyX2NjJEZBQ1NfQ1Rbc3J0X2ZpbHRlcl9jYyRgPFk3ODAvNjAtQT46IENEMTUwIFBFIEN5N2A8My41ICYgc3J0X2ZpbHRlcl9jYyRgPFk1ODIvMTUtQT46IEZsdDMgUEVgPDMuNV0gPSAiU1QgKyBNUFAzIgpzcnRfZmlsdGVyX2NjJEZBQ1NfQ1Rbc3J0X2ZpbHRlcl9jYyRgPFk3ODAvNjAtQT46IENEMTUwIFBFIEN5N2A8My41ICYgc3J0X2ZpbHRlcl9jYyRgPFk1ODIvMTUtQT46IEZsdDMgUEVgPjMuNV0gPSAiTE1QUCIKc3J0X2ZpbHRlcl9jYyRGQUNTX0NUW3NydF9maWx0ZXJfY2MkYDxWNjYwLzIwLUE+OiBJTDdSIEJWNjUwYD4zXSA9ICJDTFAiCmBgYAoKCmBgYHtyfQpEaW1QbG90KHNydF9maWx0ZXJfY2MsIGdyb3VwLmJ5ID0gIkZBQ1NfQ1QiLCBsYWJlbCA9IEZBTFNFKSt0aGVtZShsaW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ICA9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHRpdGxlID0gZWxlbWVudF9ibGFuaygpKQpnZ3NhdmUoImZpZ3MvdW1hcF9jb2xfYnlfRkFDU19nYXRlLnBkZiIsd2lkdGggPSA1LjUsaGVpZ2h0ID0gNC41KQpgYGAKCmBgYHtyfQpwMSA9IEZlYXR1cmVQbG90KHNydF9maWx0ZXJfY2MsZmVhdHVyZXMgPSBjKCJEbnR0IikscHQuc2l6ZT0wLjUsbWF4LmN1dG9mZj0icTk1IixuY29sPTQsY29scz1CbHVlQW5kUmVkKCkpK3RoZW1lKGxpbmUgPSBlbGVtZW50X2JsYW5rKCksdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQgID1lbGVtZW50X2JsYW5rKCksYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSxsZWdlbmQucG9zaXRpb249Im5vbmUiKQpwMiA9IEZlYXR1cmVQbG90KHNydF9maWx0ZXJfY2MsZmVhdHVyZXMgPSBjKCJTYXRiMSIpLHB0LnNpemU9MC41LG1heC5jdXRvZmY9InE5NSIsbmNvbD00LGNvbHM9Qmx1ZUFuZFJlZCgpKSt0aGVtZShsaW5lID0gZWxlbWVudF9ibGFuaygpLHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ICA9ZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPSJub25lIikKcDMgPSBGZWF0dXJlUGxvdChzcnRfZmlsdGVyX2NjLGZlYXR1cmVzID0gYygiTm90Y2gxIikscHQuc2l6ZT0wLjUsbWF4LmN1dG9mZj0icTk1IixuY29sPTQsY29scz1CbHVlQW5kUmVkKCkpK3RoZW1lKGxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQgID1lbGVtZW50X2JsYW5rKCksYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSx0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSxsZWdlbmQucG9zaXRpb249Im5vbmUiKQpwNCA9IEZlYXR1cmVQbG90KHNydF9maWx0ZXJfY2MsZmVhdHVyZXMgPSBjKCJWcHJlYjEiKSxwdC5zaXplPTAuNSxtYXguY3V0b2ZmPSJxOTUiLG5jb2w9NCxjb2xzPUJsdWVBbmRSZWQoKSkrdGhlbWUobGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dCAgPWVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCgpnZ2FycmFuZ2UocDEscDIscDMscDQsbmNvbD0yLG5yb3c9MikKZ2dzYXZlKCJmaWdzL3VtYXBfbWFya2VyX2dlbmVzLnBkZiIsd2lkdGggPSA1LGhlaWdodCA9IDUpCmBgYAoKYGBge3J9CnAxID0gRmVhdHVyZVBsb3Qoc3J0X2ZpbHRlcl9jYyxmZWF0dXJlcyA9IGMoIjxZNzgwLzYwLUE+OiBDRDE1MCBQRSBDeTciKSxwdC5zaXplPTAuNSxtYXguY3V0b2ZmPSJxOTUiLG5jb2w9NCxjb2xzPUJsdWVBbmRSZWQoKSkrbGFicyh0aXRsZT0iQ0QxNTAiKSt0aGVtZShsaW5lID0gZWxlbWVudF9ibGFuaygpLHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ICA9ZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPSJub25lIikKCnAyID0gRmVhdHVyZVBsb3Qoc3J0X2ZpbHRlcl9jYyxmZWF0dXJlcyA9IGMoIjxZNTgyLzE1LUE+OiBGbHQzIFBFIikscHQuc2l6ZT0wLjUsbWF4LmN1dG9mZj0icTk1IixuY29sPTQsY29scz1CbHVlQW5kUmVkKCkpK2xhYnModGl0bGU9IkNEMTM1IChGbHQzKSIpK3RoZW1lKGxpbmUgPSBlbGVtZW50X2JsYW5rKCksdGV4dD1lbGVtZW50X3RleHQoc2l6ZT0xMiksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQgID1lbGVtZW50X2JsYW5rKCksYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSxsZWdlbmQucG9zaXRpb249Im5vbmUiKQoKcDMgPSBGZWF0dXJlUGxvdChzcnRfZmlsdGVyX2NjLGZlYXR1cmVzID0gYygiPEI1MzAvMzAtQT46IERhY2gxIEdGUCIpLHB0LnNpemU9MC41LG1heC5jdXRvZmY9InE5NSIsbmNvbD00LGNvbHM9Qmx1ZUFuZFJlZCgpKStsYWJzKHRpdGxlPSIgRGFjaDEtR0ZQIikrdGhlbWUobGluZSA9IGVsZW1lbnRfYmxhbmsoKSx0ZXh0PWVsZW1lbnRfdGV4dChzaXplPTEyKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dCAgPWVsZW1lbnRfYmxhbmsoKSxheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGxlZ2VuZC5wb3NpdGlvbj0ibm9uZSIpCnA0ID0gRmVhdHVyZVBsb3Qoc3J0X2ZpbHRlcl9jYyxmZWF0dXJlcyA9IGMoIjxWNjYwLzIwLUE+OiBJTDdSIEJWNjUwIikscHQuc2l6ZT0wLjUsbWF4LmN1dG9mZj0icTk1IixuY29sPTQsY29scz1CbHVlQW5kUmVkKCkpK2xhYnModGl0bGU9IklMN1IiKSt0aGVtZShsaW5lID0gZWxlbWVudF9ibGFuaygpLHRleHQ9ZWxlbWVudF90ZXh0KHNpemU9MTIpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ICA9ZWxlbWVudF9ibGFuaygpLGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksbGVnZW5kLnBvc2l0aW9uPSJub25lIikKCmdnYXJyYW5nZShwMSxwMixwMyxwNCxuY29sPTQsbnJvdz0xKQpnZ3NhdmUoImZpZ3MvdW1hcF9tYXJrZXJfRkFDUy5wZGYiLHdpZHRoID0gMTAsaGVpZ2h0ID0gMykKYGBgCgoKYGBge3J9CmdnX2NvbG9yX2h1ZSA8LSBmdW5jdGlvbihuKSB7CiAgaHVlcyA9IHNlcSgxNSwgMzc1LCBsZW5ndGggPSBuICsgMSkKICBoY2woaCA9IGh1ZXMsIGwgPSA2NSwgYyA9IDEwMClbMTpuXQp9CnBhbCA9IGdnX2NvbG9yX2h1ZSg0KQpuYW1lcyhwYWwpID0gYygiQ0xQIiwiTE1QUCIsIkxUICsgTVBQMiIsIlNUICsgTVBQMyIpCnBkZigiZmlncy91bWFwX0xQUF9saW5lYWdlLnBkZiIpCnBsb3Qoc3J0X2ZpbHRlcl9jY0ByZWR1Y3Rpb25zJHVtYXBAY2VsbC5lbWJlZGRpbmdzLCBjb2wgPSBwYWxbc3J0X2ZpbHRlcl9jYyRGQUNTX0NUXSwgcGNoPTE2LCBjZXg9MC45LGFzcCA9IDEsYXhlcyA9IEZBTFNFLHhsYWI9JycseWxhYj0nJykKbGluZXMoc2RzQGN1cnZlcyRjdXJ2ZTMsIGx3ZD0yLCBjb2w9J2JsYWNrJykKbGVnZW5kKCd0b3BsZWZ0JyxsZWdlbmQ9bGV2ZWxzKGFzLmZhY3RvcihzcnRfZmlsdGVyX2NjJEZBQ1NfQ1QpKSxjb2w9cGFsLHBjaD0xNix0aXRsZT0iRkFDUyBnYXRpbmciKQpkZXYub2ZmKCkKCnBkZigiZmlncy91bWFwX2FsbF9saW5lYWdlLnBkZiIpCnBsb3Qoc3J0X2ZpbHRlcl9jY0ByZWR1Y3Rpb25zJHVtYXBAY2VsbC5lbWJlZGRpbmdzLCBjb2wgPSBjb2w5W3NydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzXSwgcGNoPTE2LCBjZXg9MC43LGFzcCA9IDEsYXhlcyA9IEZBTFNFLHhsYWI9JycseWxhYj0nJykKbGluZXMoc2RzLCBsd2Q9MiwgY29sPSdibGFjaycpCmxlZ2VuZCgndG9wbGVmdCcsbGVnZW5kPW5hbWVzKGNvbDkpLGNvbD1jb2w5LHBjaD0xNix0aXRsZT0iY2x1c3RlcnMiKQpkZXYub2ZmKCkKYGBgCgoKCgpgYGB7cn0KY2xwX2RlID0gRmluZE1hcmtlcnMoc3J0X2ZpbHRlcl9jYyxpZGVudC4xPSIxIixpZGVudC4yID0gIjYiLHZlcmJvc2UgPSBGQUxTRSkKY2xwX2RlJGdlbmUgPSByb3duYW1lcyhjbHBfZGUpCmNscF9scHBfZGUgPSBGaW5kTWFya2VycyhzcnRfZmlsdGVyX2NjLGlkZW50LjE9YygiMSIsIjYiKSx2ZXJib3NlID0gRkFMU0UpCmNscF9scHBfZGUgPSBjbHBfbHBwX2RlW2NscF9scHBfZGUkYXZnX2xvZ0ZDPjAsXQpjbHBfbHBwX2RlJGdlbmUgPSByb3duYW1lcyhjbHBfbHBwX2RlKQpjbHBfbHBwX3RvcCA9IGNscF9scHBfZGUgJT4lIHRvcF9uKG49MzUsd3Q9YXZnX2xvZ0ZDKSAKCmNscF9wb3MgPSBjbHBfZGUgJT4lIHRvcF9uKG49MzUsd3Q9YXZnX2xvZ0ZDKSAKY2xwX25lZyA9IGNscF9kZSAlPiUgdG9wX24obj0zNSx3dD0tYXZnX2xvZ0ZDKSAKCmNscF9scHBfdG9wID0gY2xwX2xwcF90b3BbIShjbHBfbHBwX3RvcCRnZW5lICVpbiUgYyhjbHBfcG9zJGdlbmUsY2xwX25lZyRnZW5lKSksXQoKYGBgCgoKCgoKYGBge3J9CnNydF9maWx0ZXJfY2MkTE1QUF9nYXRlID0gIm90aGVycyIKc3J0X2ZpbHRlcl9jYyRMTVBQX2dhdGVbc3J0X2ZpbHRlcl9jYyRGQUNTX0NUPT0iTE1QUCJdID0gIkxNUFAiCgpwMSA9IERpbVBsb3Qoc3J0X2ZpbHRlcl9jYywgZ3JvdXAuYnkgPSAiTE1QUF9nYXRlIiwgb3JkZXI9YygiTE1QUCIsIm90aGVycyIpLCBjb2xzID0gYygiZ3JleSIsImJsYWNrIiksIGxhYmVsID0gRkFMU0UpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIixsaW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ICA9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHRpdGxlID0gZWxlbWVudF9ibGFuaygpKQoKc3J0X2ZpbHRlcl9jYyRmbHRfZ2F0ZSA9ICJvdGhlcnMiCnNydF9maWx0ZXJfY2MkZmx0X2dhdGVbc3J0X2ZpbHRlcl9jYyRgPFk1ODIvMTUtQT46IEZsdDMgUEVgPjMuNTcgJiBzcnRfZmlsdGVyX2NjJGA8QjUzMC8zMC1BPjogRGFjaDEgR0ZQYD4yLjggJiBzcnRfZmlsdGVyX2NjJGA8VjY2MC8yMC1BPjogSUw3UiBCVjY1MGA8M10gPSAiRGFjaDErTE1QUCIKCnAyID0gRGltUGxvdChzcnRfZmlsdGVyX2NjLCBncm91cC5ieSA9ICJmbHRfZ2F0ZSIsIG9yZGVyPWMoIkRhY2gxK0xNUFAiLCJvdGhlcnMiKSwgY29scyA9IGMoImdyZXkiLCJibGFjayIpLCBsYWJlbCA9IEZBTFNFKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsbGluZSA9IGVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIGF4aXMudGV4dCAgPWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICB0aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSkKCnNydF9maWx0ZXJfY2MkTFBQX2dhdGUgPSAib3RoZXJzIgpzcnRfZmlsdGVyX2NjJExQUF9nYXRlW3NydF9maWx0ZXJfY2MkYDxZNTgyLzE1LUE+OiBGbHQzIFBFYD4zLjU3ICYgc3J0X2ZpbHRlcl9jYyRgPEI1MzAvMzAtQT46IERhY2gxIEdGUGA8Mi41ICYgc3J0X2ZpbHRlcl9jYyRgPFY2NjAvMjAtQT46IElMN1IgQlY2NTBgPDNdID0gIkxQUCIKCnAzID0gRGltUGxvdChzcnRfZmlsdGVyX2NjLCBncm91cC5ieSA9ICJMUFBfZ2F0ZSIsIG9yZGVyPWMoIkxQUCIsIm90aGVycyIpLCBjb2xzID0gYygiZ3JleSIsImJsYWNrIiksIGxhYmVsID0gRkFMU0UpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIixsaW5lID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgYXhpcy50ZXh0ICA9ZWxlbWVudF9ibGFuaygpLAogICAgICAgIHRpdGxlID0gZWxlbWVudF9ibGFuaygpKQoKc3J0X2ZpbHRlcl9jYyRDTFBfZ2F0ZSA9ICJvdGhlcnMiCnNydF9maWx0ZXJfY2MkQ0xQX2dhdGVbc3J0X2ZpbHRlcl9jYyRGQUNTX0NUPT0iQ0xQIl0gPSAiQ0xQIgoKcDQgPSBEaW1QbG90KHNydF9maWx0ZXJfY2MsIGdyb3VwLmJ5ID0gIkNMUF9nYXRlIiwgb3JkZXI9YygiQ0xQIiwib3RoZXJzIiksIGNvbHMgPSBjKCJncmV5IiwiYmxhY2siKSwgbGFiZWwgPSBGQUxTRSkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLGxpbmUgPSBlbGVtZW50X2JsYW5rKCksCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICBheGlzLnRleHQgID1lbGVtZW50X2JsYW5rKCksCiAgICAgICAgdGl0bGUgPSBlbGVtZW50X2JsYW5rKCkpCgpnZ2FycmFuZ2UocDEscDIscDMscDQsbmNvbD00LG5yb3c9MSkKZ2dzYXZlKCJmaWdzL3VtYXBfTFBQX2dhdGUucGRmIix3aWR0aCA9IDEyLGhlaWdodCA9IDMpCmBgYAoKYGBge3J9CmNvbWJpbmVkX2dhdGUgPSByZXAoIi4iLG5jb2woc3J0X2ZpbHRlcl9jYykpCmNvbWJpbmVkX2dhdGVbc3J0X2ZpbHRlcl9jYyRMTVBQX2dhdGU9PSJMTVBQIl0gPSAib3RoZXIgTE1QUHMiCmNvbWJpbmVkX2dhdGVbc3J0X2ZpbHRlcl9jYyRmbHRfZ2F0ZSA9PSJEYWNoMStMTVBQIl0gPSAiRGFjaDErTE1QUCIKY29tYmluZWRfZ2F0ZVtzcnRfZmlsdGVyX2NjJExQUF9nYXRlID09IkxQUCJdID0gIkxQUCIKY29tYmluZWRfZ2F0ZVtzcnRfZmlsdGVyX2NjJENMUF9nYXRlID09IkNMUCJdID0gIkNMUCIKYGBgCgpgYGB7cn0KZmFjc19uZXcgPSBzcnRfZmlsdGVyX2NjJEZBQ1NfQ1QKZmFjc19uZXdbY29tYmluZWRfZ2F0ZT09IkRhY2gxK0xNUFAiXSA9ICJEYWNoMStMTVBQIgpmYWNzX25ld1tjb21iaW5lZF9nYXRlPT0iTFBQIl0gPSAiTFBQIgoKZ2dwbG90KGRhdGE9TlVMTCxhZXMoeD1zcnRfZmlsdGVyX2NjJGA8WTU4Mi8xNS1BPjogRmx0MyBQRWBbIXNydF9maWx0ZXJfY2MkRkFDU19DVD09IkNMUCJdLHk9c3J0X2ZpbHRlcl9jYyRgPEI1MzAvMzAtQT46IERhY2gxIEdGUGBbIXNydF9maWx0ZXJfY2MkRkFDU19DVD09IkNMUCJdLGNvbD1mYWNzX25ld1shc3J0X2ZpbHRlcl9jYyRGQUNTX0NUPT0iQ0xQIl0pKSsKICBnZW9tX3BvaW50KHNpemU9MSkrCiAgdGhlbWVfYncoKSsKICBzY2FsZV9jb2xvcl9tYW51YWwodmFsdWVzID0gYygiTE1QUCI9IiNFN0I4MDAiLCAiTFQgKyBNUFAyIj0iIzAwQUZCQiIsIlNUICsgTVBQMyI9IiNDQzc5QTciLCJEYWNoMStMTVBQIj0iIzBDQTU1MiIsIkxQUCI9IiNFQTI0MjQiLCJDTFAiPSIjOUY0QTE4IikpICsKICAjc2NhbGVfY29sb3JfbWFudWFsKHZhbHVlcyA9IHBhbCkrCiAgbGFicyh4PSJDRDEzNSAoRmx0MykiLHk9IkRhY2gxLUdGUCIsY29sPSIiKSsKICB0aGVtZShsZWdlbmQucG9zaXRpb249InRvcCIscGFuZWwuZ3JpZC5tYWpvciA9IGVsZW1lbnRfYmxhbmsoKSwgcGFuZWwuZ3JpZC5taW5vciA9IGVsZW1lbnRfYmxhbmsoKSwKcGFuZWwuYmFja2dyb3VuZCA9IGVsZW1lbnRfYmxhbmsoKSwgYXhpcy5saW5lID0gZWxlbWVudF9saW5lKGNvbG91ciA9ICJibGFjayIpKQpnZ3NhdmUoImZpZ3MvQ0QxMzVfRGFjaDFfY29sX2J5X0ZBQ1MucGRmIix3aWR0aCA9IDQuLGhlaWdodCA9IDQuKQpgYGAKCmBgYHtyfQpwYWwgPSAgYygiTE1QUCI9IiNFN0I4MDAiLCAiTFQgKyBNUFAyIj0iIzAwQUZCQiIsIlNUICsgTVBQMyI9IiNDQzc5QTciLCJEYWNoMStMTVBQIj0iIzBDQTU1MiIsIkxQUCI9IiNFQTI0MjQiLCJDTFAiPSIjOUY0QTE4IiwiLiI9ImdyZXk4MCIpCmNvbWJpbmVkX2dhdGVfbiA9IGZhY3NfbmV3CmNvbWJpbmVkX2dhdGVfblshKHNydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzICVpbiUgc2RzQGxpbmVhZ2VzJExpbmVhZ2UzKV0gPSAiLiIKcGRmKCJmaWdzL3VtYXBfTFBQX2xpbmVhZ2UucGRmIikKcGxvdChzcnRfZmlsdGVyX2NjQHJlZHVjdGlvbnMkdW1hcEBjZWxsLmVtYmVkZGluZ3MsIGNvbCA9IHBhbFtjb21iaW5lZF9nYXRlX25dLCBwY2g9MTYsIGNleD0wLjksYXNwID0gMSxheGVzID0gRkFMU0UseGxhYj0nJyx5bGFiPScnKQpsaW5lcyhzZHNAY3VydmVzJGN1cnZlMywgbHdkPTIsIGNvbD0nYmxhY2snKQpsZWdlbmQoJ3RvcHJpZ2h0JyxsZWdlbmQ9bmFtZXMocGFsKSAsY29sPXBhbCxwY2g9MTYsdGl0bGU9IkZBQ1MgZ2F0aW5nIixwdC5jZXg9MS41LGNleD0xLjIpCmRldi5vZmYoKQoKI3BkZigiZmlncy91bWFwX2FsbF9saW5lYWdlLnBkZiIpCiNwbG90KHNydF9maWx0ZXJfY2NAcmVkdWN0aW9ucyR1bWFwQGNlbGwuZW1iZWRkaW5ncywgY29sID0gcGFsW3NydF9maWx0ZXJfY2MkRkFDU19DVF0sIHBjaD0xNiwgY2V4PTAuNyxhc3AgPSAxLGF4ZXMgPSBGQUxTRSx4bGFiPScnLHlsYWI9JycpCiNsaW5lcyhzZHMsIGx3ZD0yLCBjb2w9J2JsYWNrJykKI2xlZ2VuZCgndG9wbGVmdCcsbGVnZW5kPWxldmVscyhhcy5mYWN0b3Ioc3J0X2ZpbHRlcl9jYyRGQUNTX0NUKSksY29sPXBhbCxwY2g9MTYsdGl0bGU9IkZBQ1MgZ2F0aW5nIikKI2Rldi5vZmYoKQpgYGAKCmBgYHtyfQp0b3BfZ2UgPSBjKCJNcGwiLCJIbGYiLCJTYXRiMSIsIklsMTJhIiwiVnByZWIxIiwiQmxuayIsIkNkNzlhIiwiUmFnMSIsIlBheDUiLCJMeTZkIiwiRG50dCIsIklyZjgiLCJOb3RjaDEiLCJQbGFjOCIpCgp0bXBfbWF0ID0gc3J0X2ZpbHRlcl9jY0Bhc3NheXMkaW50ZWdyYXRlZEBzY2FsZS5kYXRhW3VuaXF1ZSh0b3BfZ2UpLHJvd25hbWVzKG9yZGVyX2RmKV0KI3RtcF9tYXQgPSB0bXBfbWF0Wyxjb2xuYW1lcyh0bXBfbWF0KSAlaW4lIHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJEZBQ1NfQ1QgJWluJSBjKCJDTFAiLCJMTVBQIildXQp0bXBfbWF0W3RtcF9tYXQ+Mi41XSA9IDIuNQp0bXBfbWF0W3RtcF9tYXQ8KC0yLjUpXSA9IC0yLjUKCmFubm9fZGYgPSBkYXRhLmZyYW1lKGNsdXN0ZXJzPXNydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzLAogICAgICAgICAgICAgICAgICAgICBGQUNTX2dhdGluZz1mYWNzX25ldywKICAgICAgICAgICAgICAgICAgICAgRGFjaDFHRlA9c3J0X2ZpbHRlcl9jYyRgPEI1MzAvMzAtQT46IERhY2gxIEdGUGAsCiAgICAgICAgICAgICAgICAgICAgIENEMTM1PXNydF9maWx0ZXJfY2MkYDxZNTgyLzE1LUE+OiBGbHQzIFBFYCwKICAgICAgICAgICAgICAgICAgICAgQ0QxMjc9c3J0X2ZpbHRlcl9jYyRgPFY2NjAvMjAtQT46IElMN1IgQlY2NTBgLAogICAgICAgICAgICAgICAgICAgICAjQ0QxNTA9c3J0X2ZpbHRlcl9jYyRgPFk3ODAvNjAtQT46IENEMTUwIFBFIEN5N2AsCiAgICAgICAgICAgICAgICAgICAgIHN0cmluZ3NBc0ZhY3RvcnMgPSBGQUxTRSkKCmFubm90YXRpb25fY29sb3JzID0gbGlzdCgKICBjbHVzdGVycz1jb2w5LAogIERhY2gxR0ZQPUJsdWVBbmRSZWQoKSwKICBDRDE1MD1CbHVlQW5kUmVkKCksCiAgQ0QxMzU9Qmx1ZUFuZFJlZCgpLAogIENEMTI3PUJsdWVBbmRSZWQoKSwKICBwcm9CX0NMUF9CTT1CbHVlQW5kUmVkKCksCiAgU0NfQ01QX0JNPUJsdWVBbmRSZWQoKSwKICBTQ19NRVBfQk09Qmx1ZUFuZFJlZCgpLAogIFNDX1NUU0xfQk09Qmx1ZUFuZFJlZCgpLAogIFNDX0xUU0xfQk09Qmx1ZUFuZFJlZCgpLAogIEZBQ1NfZ2F0aW5nPXBhbAopCgpwaGVhdG1hcCh0bXBfbWF0LAogICAgICAgICBjbHVzdGVyX2NvbHMgPSBGQUxTRSwgCiAgICAgICAgIGNsdXN0ZXJfcm93cyA9IFRSVUUsCiAgICAgICAgIGFubm90YXRpb25fY29sID0gYW5ub19kZiwKICAgICAgICAgYW5ub3RhdGlvbl9jb2xvcnM9YW5ub3RhdGlvbl9jb2xvcnMsCiAgICAgICAgIHNob3dfY29sbmFtZXMgPSBGQUxTRSwKICAgICAgICAgY29sb3I9UHVycGxlQW5kWWVsbG93KCksCiAgICAgICAgIGZpbGVuYW1lPSJmaWdzL2hlYXRtYXBfc2xpbmdzaG90X1MucGRmIix3aWR0aCA9IDUsaGVpZ2h0ID0gMy41KQoKcGhlYXRtYXAodG1wX21hdCwKICAgICAgICAgY2x1c3Rlcl9jb2xzID0gRkFMU0UsIAogICAgICAgICBjbHVzdGVyX3Jvd3MgPSBUUlVFLAogICAgICAgICBhbm5vdGF0aW9uX2NvbCA9IGFubm9fZGYsCiAgICAgICAgIGFubm90YXRpb25fY29sb3JzPWFubm90YXRpb25fY29sb3JzLAogICAgICAgICBzaG93X2NvbG5hbWVzID0gRkFMU0UsCiAgICAgICAgIGNvbG9yPVB1cnBsZUFuZFllbGxvdygpLAogICAgICAgICBmaWxlbmFtZT0iZmlncy9oZWF0bWFwX3NsaW5nc2hvdF9MLnBkZiIsd2lkdGggPSA2LjUsaGVpZ2h0ID0gMTApCmBgYAoKCmBgYHtyfQpzcnRfZmlsdGVyX2NjJGNscF9scHBfZ2F0ZSA9IHNydF9maWx0ZXJfY2MkQ0xQX2dhdGUgCnNydF9maWx0ZXJfY2MkY2xwX2xwcF9nYXRlW3NydF9maWx0ZXJfY2MkTFBQX2dhdGU9PSJMUFAiXSA9ICJMUFAiCgpzcnRfZmlsdGVyX2NjX2xwcCA9IHNydF9maWx0ZXJfY2NbLCEoc3J0X2ZpbHRlcl9jYyRjbHBfbHBwX2dhdGUgPT0gIm90aGVycyIpXQpgYGAKCgpgYGB7cn0KcDEgPSBWbG5QbG90KHNydF9maWx0ZXJfY2NfbHBwLGZlYXR1cmVzPWMoIklsMTJhIikscHQuc2l6ZT0wLjMsZ3JvdXAuYnk9ImNscF9scHBfZ2F0ZSIpK3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNGQTlBOTUiLCIjQzMwMDAwIikpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIixheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQpwMiA9IFZsblBsb3Qoc3J0X2ZpbHRlcl9jY19scHAsZmVhdHVyZXM9YygiU2F0YjEiKSxwdC5zaXplPTAuMyxncm91cC5ieT0iY2xwX2xwcF9nYXRlIikrc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0ZBOUE5NSIsIiNDMzAwMDAiKSkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpCnAzID0gVmxuUGxvdChzcnRfZmlsdGVyX2NjX2xwcCxmZWF0dXJlcz1jKCJNYWNyb2gyYTEiKSxwdC5zaXplPTAuMyxncm91cC5ieT0iY2xwX2xwcF9nYXRlIikrc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0ZBOUE5NSIsIiNDMzAwMDAiKSkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpCnA0ID0gVmxuUGxvdChzcnRfZmlsdGVyX2NjX2xwcCxmZWF0dXJlcz1jKCJOY2YxIikscHQuc2l6ZT0wLjMsZ3JvdXAuYnk9ImNscF9scHBfZ2F0ZSIpK3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNGQTlBOTUiLCIjQzMwMDAwIikpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIixheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQpwNSA9IFZsblBsb3Qoc3J0X2ZpbHRlcl9jY19scHAsZmVhdHVyZXM9YygiSXJmOCIpLHB0LnNpemU9MC4zLGdyb3VwLmJ5PSJjbHBfbHBwX2dhdGUiKStzY2FsZV9maWxsX21hbnVhbCh2YWx1ZXMgPSBjKCIjRkE5QTk1IiwiI0MzMDAwMCIpKSt0aGVtZShsZWdlbmQucG9zaXRpb24gPSAibm9uZSIsYXhpcy50aXRsZSA9IGVsZW1lbnRfYmxhbmsoKSxheGlzLnRleHQueCA9IGVsZW1lbnRfYmxhbmsoKSkKcDYgPSBWbG5QbG90KHNydF9maWx0ZXJfY2NfbHBwLGZlYXR1cmVzPWMoIkRudHQiKSxwdC5zaXplPTAuMyxncm91cC5ieT0iY2xwX2xwcF9nYXRlIikrc2NhbGVfZmlsbF9tYW51YWwodmFsdWVzID0gYygiI0ZBOUE5NSIsIiNDMzAwMDAiKSkrdGhlbWUobGVnZW5kLnBvc2l0aW9uID0gIm5vbmUiLGF4aXMudGl0bGUgPSBlbGVtZW50X2JsYW5rKCksYXhpcy50ZXh0LnggPSBlbGVtZW50X2JsYW5rKCkpCnA3ID0gVmxuUGxvdChzcnRfZmlsdGVyX2NjX2xwcCxmZWF0dXJlcz1jKCJSYWcxIikscHQuc2l6ZT0wLjMsZ3JvdXAuYnk9ImNscF9scHBfZ2F0ZSIpK3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNGQTlBOTUiLCIjQzMwMDAwIikpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIixheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQpwOCA9IFZsblBsb3Qoc3J0X2ZpbHRlcl9jY19scHAsZmVhdHVyZXM9YygiVnByZWIzIikscHQuc2l6ZT0wLjMsZ3JvdXAuYnk9ImNscF9scHBfZ2F0ZSIpK3NjYWxlX2ZpbGxfbWFudWFsKHZhbHVlcyA9IGMoIiNGQTlBOTUiLCIjQzMwMDAwIikpK3RoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9ICJub25lIixheGlzLnRpdGxlID0gZWxlbWVudF9ibGFuaygpLGF4aXMudGV4dC54ID0gZWxlbWVudF9ibGFuaygpKQoKZ2dhcnJhbmdlKHAxLHAyLHAzLHA0LHA1LHA2LHA3LHA4LG5jb2w9Mixucm93PTQsaGp1c3Q9VCkKZ2dzYXZlKCJmaWdzL3Zsbl9wbG90X21hcmtlcl9MUFBDTFAucGRmIix3aWR0aCA9IDUsaGVpZ2h0ID0gNikKYGBgCgpgYGB7cn0KdGFibGUoc3J0X2ZpbHRlcl9jY19scHBAYXNzYXlzJGludGVncmF0ZWRAc2NhbGUuZGF0YVsiUmFnMSIsc3J0X2ZpbHRlcl9jY19scHAkY2xwX2xwcF9nYXRlPT0iTFBQIl0+MSlbMl0vc3VtKHRhYmxlKHNydF9maWx0ZXJfY2NfbHBwQGFzc2F5cyRpbnRlZ3JhdGVkQHNjYWxlLmRhdGFbIlJhZzEiLHNydF9maWx0ZXJfY2NfbHBwJGNscF9scHBfZ2F0ZT09IkxQUCJdPjEpKQoKdGFibGUoc3J0X2ZpbHRlcl9jY19scHBAYXNzYXlzJGludGVncmF0ZWRAc2NhbGUuZGF0YVsiUmFnMSIsc3J0X2ZpbHRlcl9jY19scHAkY2xwX2xwcF9nYXRlPT0iQ0xQIl0+MSlbMl0vc3VtKHRhYmxlKHNydF9maWx0ZXJfY2NfbHBwQGFzc2F5cyRpbnRlZ3JhdGVkQHNjYWxlLmRhdGFbIlJhZzEiLHNydF9maWx0ZXJfY2NfbHBwJGNscF9scHBfZ2F0ZT09IkNMUCJdPjEpKQpgYGAKCgoKYGBge3J9CnNydF9maWx0ZXJfY2Nfc2VsID0gc3J0X2ZpbHRlcl9jYwoKc3J0X2ZpbHRlcl9jY19zZWwgPSBzcnRfZmlsdGVyX2NjX3NlbFssc3J0X2ZpbHRlcl9jY19zZWwkc2V1cmF0X2NsdXN0ZXJzICVpbiUgYygxLDYpXQoKRG90UGxvdChzcnRfZmlsdGVyX2NjX3NlbCwgZmVhdHVyZXMgPSBjKCJWcHJlYjEiLCJCbG5rIiwiQ2Q3OWEiLCJSYWcxIiwiUGF4NSIsIkx5NmQiLCJEbnR0IiwiSXJmOCIsIk5vdGNoMSIsIlBsYWM4IiwiU2F0YjEiLCJJbDEyYSIpLCBkb3Quc2NhbGUgPSA4KSArIFJvdGF0ZWRBeGlzKCkKYGBgCgpgYGB7cn0Kc3J0X2ZpbHRlcl9jYy5tYXJrZXJzX3NlbCA9IHNydF9maWx0ZXJfY2MubWFya2Vyc1tzcnRfZmlsdGVyX2NjLm1hcmtlcnMkcF92YWxfYWRqPDAuMDAxLF0Kc3J0X2ZpbHRlcl9jYy5tYXJrZXJzX3NlbCRjbHVzdGVyID0gYXMubnVtZXJpYyhzcnRfZmlsdGVyX2NjLm1hcmtlcnNfc2VsJGNsdXN0ZXIpCndyaXRlLmNzdihzcnRfZmlsdGVyX2NjLm1hcmtlcnNfc2VsLGZpbGUgPSAic2NSTkFzZXFfU2V1cmF0X21hcmtlcnMuY3N2Iixyb3cubmFtZXMgPSBGQUxTRSkKYGBgCgpgYGB7cn0KdGFibGUoc3J0X2ZpbHRlcl9jYyRMUFBfZ2F0ZT09IkxQUCIsc3J0X2ZpbHRlcl9jYyRzZXVyYXRfY2x1c3RlcnMpCnRhYmxlKHNydF9maWx0ZXJfY2MkZmx0X2dhdGU9PSJmbHQzX2hpZ2giLHNydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzKQpgYGAKCmBgYHtyfQpWZW5uRGlhZ3JhbTo6dmVubi5kaWFncmFtKGxpc3Qocm93bmFtZXMoc3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGEpW3NydF9maWx0ZXJfY2MkZmx0X2dhdGU9PSJmbHQzX2hpZ2giXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJHNldXJhdF9jbHVzdGVycyA9PSAxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcnkubmFtZXMgPSBjKCJmbHQzX2hpZ2giLCJjbHVzdGVyMiIpLGZpbGVuYW1lPSJ2ZW5uX2ZsdGhpZ2gudGlmZiIpCgpWZW5uRGlhZ3JhbTo6dmVubi5kaWFncmFtKGxpc3Qocm93bmFtZXMoc3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGEpW3NydF9maWx0ZXJfY2MkTFBQX2dhdGU9PSJMUFAiXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJHNldXJhdF9jbHVzdGVycyA9PSAxXSksCiAgICAgICAgICAgICAgICAgICAgICAgICAgY2F0ZWdvcnkubmFtZXMgPSBjKCJMUFAiLCJjbHVzdGVyMiIpLGZpbGVuYW1lPSJ2ZW5uX0xQUC50aWZmIikKClZlbm5EaWFncmFtOjp2ZW5uLmRpYWdyYW0obGlzdChyb3duYW1lcyhzcnRfZmlsdGVyX2NjQG1ldGEuZGF0YSlbc3J0X2ZpbHRlcl9jYyRMTVBQX2dhdGU9PSJMTVBQIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3duYW1lcyhzcnRfZmlsdGVyX2NjQG1ldGEuZGF0YSlbc3J0X2ZpbHRlcl9jYyRzZXVyYXRfY2x1c3RlcnMgPT0gMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5Lm5hbWVzID0gYygiTE1QUCIsImNsdXN0ZXIyIiksZmlsZW5hbWU9InZlbm5fTE1QUC50aWZmIikKClZlbm5EaWFncmFtOjp2ZW5uLmRpYWdyYW0obGlzdChyb3duYW1lcyhzcnRfZmlsdGVyX2NjQG1ldGEuZGF0YSlbc3J0X2ZpbHRlcl9jYyRDTFBfZ2F0ZT09IkNMUCJdLAogICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgcm93bmFtZXMoc3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGEpW3NydF9maWx0ZXJfY2MkTFBQX2dhdGU9PSJMUFAiXSwKICAgICAgICAgICAgICAgICAgICAgICAgICAgICAgIHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJGZsdF9nYXRlPT0iZmx0M19oaWdoIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3duYW1lcyhzcnRfZmlsdGVyX2NjQG1ldGEuZGF0YSlbc3J0X2ZpbHRlcl9jYyRMTVBQX2dhdGU9PSJMTVBQIl0sCiAgICAgICAgICAgICAgICAgICAgICAgICAgICAgICByb3duYW1lcyhzcnRfZmlsdGVyX2NjQG1ldGEuZGF0YSlbc3J0X2ZpbHRlcl9jYyRzZXVyYXRfY2x1c3RlcnMgPT0gMV0pLAogICAgICAgICAgICAgICAgICAgICAgICAgIGNhdGVnb3J5Lm5hbWVzID0gYygiQ0xQIiwiTFBQIiwiZmx0M19oaWdoIiwiTE1QUCIsImNsdXN0ZXIyIiksZmlsZW5hbWU9InZlbm5fYWxsLnRpZmYiKQpgYGAKCgpgYGB7cn0Kd3JpdGUuY3N2KHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJENMUF9nYXRlPT0iQ0xQIl0sZmlsZSA9ICJDTFBfY2VsbHMuY3N2IixxdW90ZSA9IEZBTFNFLHJvdy5uYW1lcyA9IEZBTFNFKQp3cml0ZS5jc3Yocm93bmFtZXMoc3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGEpW3NydF9maWx0ZXJfY2MkZmx0X2dhdGU9PSJmbHQzX2hpZ2giXSxmaWxlID0gImZsdDNfaGlnaF9jZWxscy5jc3YiLHF1b3RlID0gRkFMU0Uscm93Lm5hbWVzID0gRkFMU0UpCndyaXRlLmNzdihyb3duYW1lcyhzcnRfZmlsdGVyX2NjQG1ldGEuZGF0YSlbc3J0X2ZpbHRlcl9jYyRMUFBfZ2F0ZT09IkxQUCJdLGZpbGUgPSAiTFBQX2NlbGxzLmNzdiIscXVvdGUgPSBGQUxTRSxyb3cubmFtZXMgPSBGQUxTRSkKd3JpdGUuY3N2KHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJExNUFBfZ2F0ZT09IkxNUFAiXSxmaWxlID0gIkxNUFBfY2VsbHMuY3N2IixxdW90ZSA9IEZBTFNFLHJvdy5uYW1lcyA9IEZBTFNFKQoKd3JpdGUuY3N2KHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJHNldXJhdF9jbHVzdGVycyA9PSAxXSxmaWxlID0gIkNMMl9jZWxscy5jc3YiLHF1b3RlID0gRkFMU0Uscm93Lm5hbWVzID0gRkFMU0UpCmBgYAoKCmBgYHtyfQpDTFBfYyA9IHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJENMUF9nYXRlPT0iQ0xQIl0KZmx0M19jID0gcm93bmFtZXMoc3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGEpW3NydF9maWx0ZXJfY2MkZmx0X2dhdGU9PSJmbHQzX2hpZ2giXQpMUFBfYyA9IHJvd25hbWVzKHNydF9maWx0ZXJfY2NAbWV0YS5kYXRhKVtzcnRfZmlsdGVyX2NjJExQUF9nYXRlPT0iTFBQIl0KTE1QUF9jID0gcm93bmFtZXMoc3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGEpW3NydF9maWx0ZXJfY2MkTE1QUF9nYXRlPT0iTE1QUCJdCmNsMl9jID0gcm93bmFtZXMoc3J0X2ZpbHRlcl9jY0BtZXRhLmRhdGEpW3NydF9maWx0ZXJfY2Mkc2V1cmF0X2NsdXN0ZXJzID09IDFdCgpjbDJfaW5fb3RoZXJzID0gYyhzdW0oY2wyX2MgJWluJSBDTFBfYyksCiAgICAgICAgICAgICAgICAgIHN1bShjbDJfYyAlaW4lIGZsdDNfYyksCiAgICAgICAgICAgICAgICAgIHN1bShjbDJfYyAlaW4lIExQUF9jKSwKICAgICAgICAgICAgICAgICAgc3VtKGNsMl9jICVpbiUgTE1QUF9jKSkKCmMxID0gYyhzdW0oIShjbDJfYyAlaW4lIENMUF9jKSksCiAgICAgICAgICAgICAgICAgIHN1bSghKGNsMl9jICVpbiUgZmx0M19jKSksCiAgICAgICAgICAgICAgICAgIHN1bSghKGNsMl9jICVpbiUgTFBQX2MpKSwKICAgICAgICAgICAgICAgICAgc3VtKCEoY2wyX2MgJWluJSBMTVBQX2MpKSkKCmMyID0gYyhzdW0oIShDTFBfYyAlaW4lIGNsMl9jKSksCiAgICAgICAgICAgICAgICAgIHN1bSghKGZsdDNfYyAlaW4lIGNsMl9jKSksCiAgICAgICAgICAgICAgICAgIHN1bSghKExQUF9jICAlaW4lIGNsMl9jKSksCiAgICAgICAgICAgICAgICAgIHN1bSghKExNUFBfYyAlaW4lIGNsMl9jKSkpCgpjbDJfaW5fb3RoZXJzCnggPSBjbDJfaW5fb3RoZXJzL2xlbmd0aChjbDJfYykKeSA9IGNsMl9pbl9vdGhlcnMvYyhsZW5ndGgoQ0xQX2MpLAogICAgICAgICAgICAgICAgbGVuZ3RoKGZsdDNfYyksCiAgICAgICAgICAgICAgICBsZW5ndGgoTFBQX2MpLAogICAgICAgICAgICAgICAgbGVuZ3RoKExNUFBfYykpCmBgYAoKYGBge3J9CnBsb3QoeCx5KQp0ZXh0KHgseSwgYygiQ0xQIiwiRkxUM19oaWdoIiwiTFBQIiwiTE1QUCIpLAogICAgIGNleD0wLjY1LCBwb3M9MSxjb2w9InJlZCIpIApgYGAKCgpgYGB7cn0KCmBgYAoK